The TypeScript compiler is complaining because you’re trying to pass an argument to a function that doesn’t match the type the function expects. This happens when the shape or specific type of the data you’re providing doesn’t align with the function’s defined parameters.
Here’s a breakdown of the most common reasons for this error and how to fix them:
1. Mismatched Primitive Types
The most frequent culprit is passing a number where a string is expected, or vice-versa.
- Diagnosis: Hover over the variable or expression you’re passing as an argument in your IDE. It will show you the inferred type. Then, check the function’s signature to see the expected type.
- Fix: Explicitly convert the type. If you have a number
myNumand need to pass it as a string:
If you have a string that should be a number, usefunction processString(input: string) { console.log(input.toUpperCase()); } let myNum: number = 123; // Incorrect: TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. // processString(myNum); // Correct: Convert the number to a string processString(myNum.toString());parseInt()orparseFloat():function sum(a: number, b: number): number { return a + b; } let priceString: string = "19.99"; // Incorrect: TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. // sum(10, priceString); // Correct: Convert the string to a number sum(10, parseFloat(priceString)); - Why it works: TypeScript enforces type safety.
toString()guarantees the output is a string, andparseFloat()guarantees a number, satisfying the function’s signature.
2. Missing or Extra Properties in Object Literals
When passing an object to a function, the object must have at least the properties the function expects, with matching types.
- Diagnosis: Examine the function signature’s parameter type. Compare it against the object literal you are providing.
- Fix: Ensure all required properties are present and have the correct types. If the function expects an object with
name: stringandage: number:interface User { name: string; age: number; } function greetUser(user: User) { console.log(`Hello, ${user.name}! You are ${user.age} years old.`); } // Incorrect: Missing 'age' property // greetUser({ name: "Alice" }); // Incorrect: 'age' is the wrong type // greetUser({ name: "Bob", age: "twenty" }); // Correct: All properties present with correct types greetUser({ name: "Charlie", age: 30 }); - Why it works: The object literal now conforms to the
Userinterface, satisfying theuser: Userparameter type.
3. Union Types and Specificity
You might be passing a variable that could be one of several types (a union type), but the function expects a specific type within that union.
- Diagnosis: Check the type of your variable and the expected parameter type. If your variable is
string | numberand the function expectsstring, you’ll get this error. - Fix: Narrow down the union type before passing it.
function processOnlyStrings(input: string) { console.log(`Processing string: ${input}`); } let data: string | number = "hello"; // Incorrect: TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'. // processOnlyStrings(data); // Correct: Check the type before passing if (typeof data === 'string') { processOnlyStrings(data); } - Why it works: The
typeof data === 'string'check acts as a type guard, assuring TypeScript thatdatais indeed astringwithin that block, making it assignable to thestringparameter.
4. null or undefined Being Passed to Non-Nullable Types
By default, null and undefined are not assignable to any type unless strictNullChecks is off or the type explicitly includes null or undefined in a union.
- Diagnosis: Inspect the variable you are passing. If it could potentially be
nullorundefined, and the function parameter does not allow it (e.g.,param: stringinstead ofparam: string | null), this error will occur. - Fix: Add checks to ensure the value is not
nullorundefined, or modify the function signature ifnull/undefinedare valid inputs.function displayMessage(message: string) { console.log(message); } let userMessage: string | null = null; // Could be null // Incorrect: TS2345: Argument of type 'string | null' is not assignable to parameter of type 'string'. // displayMessage(userMessage); // Correct: Check for null if (userMessage !== null) { displayMessage(userMessage); } // Alternative Correct: If the function CAN accept null, modify its signature function displayOptionalMessage(message: string | null) { console.log(message ?? "No message provided"); } displayOptionalMessage(userMessage); // This now works - Why it works: The check
userMessage !== nullensures that only a validstringis passed. Alternatively, modifying the function signature tostring | nullexplicitly tells TypeScript thatnullis an acceptable input.
5. Mismatched Function Types
You might be trying to pass a function as an argument, but its signature (parameters and return type) doesn’t match what the receiving function expects.
- Diagnosis: Compare the type of the function you’re providing with the type expected by the parameter.
- Fix: Adjust your function to match the required signature.
function executeCallback(callback: (value: number) => void) { callback(42); } // Incorrect: Callback expects a number, but receives a string // executeCallback((val: string) => console.log(`Received: ${val}`)); // Incorrect: Callback returns a string, but expects void (no return) // executeCallback((val: number) => `The number is ${val}`); // Correct: Callback matches the signature executeCallback((val: number) => { console.log(`Processing number: ${val}`); }); - Why it works: The provided callback now precisely matches the
(value: number) => voidsignature, fulfilling theexecuteCallbackfunction’s requirement.
6. Generics and Type Arguments
When working with generic functions or classes, you might forget to provide the correct type argument, or the inferred type argument is not compatible.
- Diagnosis: Look at the generic function call. If it’s
myGenericFunc(arg), TypeScript might infer the type. If it’smyGenericFunc<SomeType>(arg), ensureSomeTypeis correct. Check the generic constraint. - Fix: Explicitly provide the type argument or ensure the inferred type is correct.
function identity<T>(arg: T): T { return arg; } let output1 = identity("myString"); // T is inferred as string let output2 = identity(100); // T is inferred as number function processStringOnly<T extends string>(arg: T): void { // Constraint: T must be a string console.log(arg.length); } // Incorrect: TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. // processStringOnly(123); // Correct: Pass a string processStringOnly("hello"); // Correct: Explicitly provide type argument if inference is tricky let numValue = 5; // Incorrect: TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. // processStringOnly<number>(numValue); // Correct: processStringOnly<string>(numValue.toString()); - Why it works: The
<T extends string>constraint onprocessStringOnlyenforces that only string types (or subtypes) can be passed. ProvidingnumValue.toString()satisfies this constraint.
The next error you’ll likely encounter after fixing these is related to return types not matching, or perhaps a missing semicolon if you’re in a particularly strict linter configuration.