Learn why TypeScript throws TS2345 when passing wrong argument types to functions, and how to fix parameter type mismatch errors.
TS2345 is TypeScript's way of telling you that a function expected one type of argument but you gave it something else. It's essentially the function-call version of TS2322.
Every function parameter has an expected type, whether it's explicitly annotated or inferred. When you call that function, TypeScript checks each argument against the corresponding parameter type. If any argument doesn't match, you get TS2345.
// The general shape of the error:
// Argument of type 'string' is not assignable to parameter of type 'number'.
// ~~~~~~ ~~~~~~
// what you passed what was expectedThe most straightforward case. A function expects a number, you gave it a string.
// ❌ Broken
function calculateShippingCost(weightInKg: number): number {
return weightInKg * 5.99
}
const userInput = "3.5" // string from a form input
const cost = calculateShippingCost(userInput)
// ~~~~~~~~~ Error: Argument of type 'string' is not
// assignable to parameter of type 'number'.// ✅ Fixed — convert the value before passing it
const userInput = "3.5"
const cost = calculateShippingCost(Number(userInput))null or undefined to a Non-Nullable ParameterWith strictNullChecks enabled (which it should be), null and undefined are not assignable to other types unless explicitly included.
// ❌ Broken
function greetUser(username: string): string {
return `Welcome back, ${username}!`
}
const currentUser = localStorage.getItem("username") // string | null
greetUser(currentUser)
// ~~~~~~~~~~~ Error: Argument of type 'string | null' is not
// assignable to parameter of type 'string'.// ✅ Fixed — handle the null case
const currentUser = localStorage.getItem("username")
if (currentUser !== null) {
greetUser(currentUser) // OK — TypeScript narrowed to string
}
// Or provide a default
greetUser(currentUser ?? "Guest")When a function expects an object with specific properties, passing an object that's missing some of them triggers TS2345.
// ❌ Broken
interface EmailOptions {
to: string
subject: string
body: string
}
function sendEmail(options: EmailOptions) { /* ... */ }
sendEmail({ to: "user@example.com", subject: "Hello" })
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Error: Argument of type '{ to: string; subject: string; }' is not assignable
// to parameter of type 'EmailOptions'. Property 'body' is missing.// ✅ Fixed — include all required properties
sendEmail({
to: "user@example.com",
subject: "Hello",
body: "Thanks for signing up!",
})This often appears with array methods like .map(), .filter(), or .reduce() when the callback's return type doesn't match what the generic expects.
// ❌ Broken
const orderTotals: number[] = [29.99, 49.99, 14.99]
const formatted = orderTotals.map((total) => `$${total.toFixed(2)}`)
// formatted is string[] — that's fine
const roundedTotals: number[] = orderTotals.map((total) => `$${total.toFixed(2)}`)
// Error: Type 'string[]' is not assignable to type 'number[]'.// ✅ Fixed — return the correct type from the callback
const roundedTotals: number[] = orderTotals.map((total) => Math.round(total))Read the error carefully. TypeScript tells you the argument position, the type you passed, and the type that was expected. Start by understanding the mismatch.
Inspect the function signature. Go to the function definition (Cmd/Ctrl+Click in most editors) and look at what each parameter expects.
Check the argument's type. Hover over the variable you're passing to see what TypeScript inferred. The inferred type might be wider than you expected (e.g., string | null instead of string).
Choose your fix:
| Situation | Fix |
|---|---|
| Value is the wrong type | Convert it (e.g., Number(), String()) |
| Value might be null/undefined | Add a null check or use ?? |
| Object is missing properties | Add the missing properties |
| Function signature is too strict | Widen the parameter type |
For generic functions, make sure the types flow through correctly. If a callback returns the wrong type, fix the callback rather than casting.
// Type-safe approach with generics
function transformItems<T, U>(items: T[], transform: (item: T) => U): U[] {
return items.map(transform)
}
// TypeScript infers U as string from the callback
const labels = transformItems([1, 2, 3], (n) => `Item ${n}`)TS2345 occurs when you call a function and one of the arguments you pass doesn't match the type the function expects for that parameter. It is the function-call equivalent of TS2322.
Common triggers include:
null or undefined to a parameter that doesn't allow itStart by checking the function signature to see what types are expected, then look at what type you're actually passing. The fix usually falls into one of these categories:
// Convert the value
calculateTotal(Number(priceString))
// Narrow nullable values
if (user !== null) {
greetUser(user)
}
// Provide defaults
greetUser(username ?? "Anonymous")
// Add missing properties to objects
sendEmail({ to, subject, body: "" })Avoid using as assertions to force the types to match. If the types genuinely don't align, the assertion just moves the error from compile time to runtime.
Both errors are about type mismatches, but they appear in different contexts:
// TS2322 — assignment context
const count: number = "five"
// TS2345 — function argument context
function double(n: number) { return n * 2 }
double("five")Under the hood, both enforce the same assignability rules. The distinction helps you locate the problem: TS2322 points you to an assignment, TS2345 points you to a function call.
Get the latest TypeScript tips, tutorials, and course updates delivered straight to your inbox.