This error occurs when you pass a string argument to a function that expects a number parameter. TypeScript enforces strict type checking to prevent runtime errors. The fix involves converting the string to a number using parseInt(), parseFloat(), Number(), or the unary plus operator before passing it to the function.
This TypeScript error indicates a type mismatch between what you are passing to a function and what the function expects. Specifically, you are trying to pass a string value to a parameter that has been declared as accepting only numbers. TypeScript is a statically-typed language that checks types at compile time rather than runtime. When TypeScript detects that you are passing incompatible types, it raises this error to prevent you from introducing bugs that would only manifest at runtime. This is one of the core strengths of TypeScript—catching type mismatches before your code runs. The error usually appears in three common scenarios: calling a function with the wrong type, assigning a value to a variable with an incompatible type, or passing arguments to constructors or methods that expect specific types.
Look at the function call or assignment that triggered the error. Determine where the string is coming from. Common sources include:
- User input (form fields, text inputs)
- API responses or fetch() results
- Environment variables (process.env.*)
- Database query results
- File I/O operations
- JSON data
- URL parameters or query strings
For example, if you see processAge(userInput) where userInput is a string, that's the problem.
TypeScript provides several ways to convert strings to numbers. Pick the one that fits your use case:
// Method 1: Number() - Converts entire string to number
const str = "42";
const num = Number(str); // 42
// Method 2: parseInt() - Extracts integer, ignores decimal part
const str2 = "42.99";
const int = parseInt(str2, 10); // 42 (always include radix 10 for decimal)
// Method 3: parseFloat() - Preserves decimal values
const str3 = "42.99";
const float = parseFloat(str3); // 42.99
// Method 4: Unary plus (+) - Quick coercion (less explicit)
const str4 = "42";
const num4 = +str4; // 42Apply the conversion at the call site, right before passing the value to the function:
// WRONG - causes TypeScript error
function calculatePrice(quantity: number): number {
return quantity * 10;
}
const userInput = "5"; // From form field
calculatePrice(userInput); // Error: string not assignable to number
// CORRECT - convert the string first
const quantity = parseInt(userInput, 10);
calculatePrice(quantity); // OK
// Or inline the conversion
calculatePrice(parseInt(userInput, 10)); // OKUse isNaN() to check if the conversion failed. Conversion functions like parseInt() and parseFloat() do not throw errors; they return NaN for invalid input.
const userInput = "hello"; // Not a valid number
const num = parseInt(userInput, 10); // Returns NaN
if (isNaN(num)) {
console.error("Invalid number provided:", userInput);
// Handle the error appropriately
} else {
processNumber(num);
}
// Alternative: Use Number() with additional validation
const num2 = Number(userInput);
if (Number.isNaN(num2) || !Number.isFinite(num2)) {
console.error("Invalid number");
}For complex applications, use Zod, io-ts, or TypeScript type guards to validate input at the boundary (API endpoints, form handlers, etc.):
// Using Zod
import { z } from "zod";
const schema = z.object({
quantity: z.string().transform(Number).pipe(z.number().positive())
});
const data = schema.parse({ quantity: "42" }); // Automatically converts and validates
processQuantity(data.quantity); // Type is number
// Using a type guard
function isNumber(value: unknown): value is number {
return typeof value === "number" && !isNaN(value);
}
const value = parseFloat(userInput);
if (isNumber(value)) {
processNumber(value); // Safe to use
}If your function legitimately needs to accept both strings and numbers, use function overloads to make the intent clear and handle both cases:
// Define overloads
function processValue(value: number): void;
function processValue(value: string): void;
// Implementation
function processValue(value: number | string): void {
const num = typeof value === "string" ? parseInt(value, 10) : value;
if (isNaN(num)) {
console.error("Invalid value");
return;
}
console.log("Processing:", num);
}
processValue(42); // OK
processValue("42"); // OK
processValue("hello"); // Runtime error (caught with isNaN)When working with JSON data, remember that JSON numbers become JavaScript numbers when parsed, but numbers in JSON strings (like "42") remain strings even after JSON.parse(). Always check your API response types. For form inputs, all values are strings by default in HTML, so conversion is essential. Be cautious with parseInt() on strings without a radix parameter—"08" with no radix may be parsed as octal in older browsers. Always specify radix 10 for decimal integers. When working with large numbers (beyond JavaScript's safe integer limit of 2^53 - 1), consider using BigInt instead. If you're processing CSV, XML, or other text formats, the string conversion problem is pervasive—validate early in your data pipeline. In TypeScript strict mode (recommended), implicit any coercions are disabled, making these type errors more visible and easier to catch during development rather than in production.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript