🔧 Error Fixes
· 2 min read
Last updated on
TypeScript: Argument of Type X Is Not Assignable to Parameter of Type Y
Argument of type 'string' is not assignable to parameter of type 'number'
What causes this
You’re passing a value of one type to a function that expects a different type. TypeScript’s type system caught a mismatch between what you’re providing and what the function signature requires.
Common scenarios:
- Passing a string where a number is expected (or vice versa)
- Passing a broad type (
string) where a narrow literal type is expected ('success' | 'error') - Object missing required properties
- Passing
nullorundefinedto a non-nullable parameter - Using the return value of one function as input to another with incompatible types
Fix 1: Convert the type
function setPort(port: number) { /* ... */ }
// ❌ string is not assignable to number
const port = process.env.PORT; // string | undefined
setPort(port);
// ✅ Convert to number
setPort(Number(process.env.PORT) || 3000);
setPort(parseInt(process.env.PORT ?? '3000', 10));
Fix 2: Narrow string literals with as const
type Status = 'success' | 'error' | 'pending';
function setStatus(status: Status) { /* ... */ }
// ❌ Type 'string' is not assignable to type 'Status'
const s = 'success'; // TypeScript infers: string
setStatus(s);
// ✅ Use const assertion
const s = 'success' as const; // TypeScript infers: 'success'
setStatus(s);
// ✅ Or annotate the variable
const s: Status = 'success';
setStatus(s);
Fix 3: Add missing properties to objects
interface User {
name: string;
email: string;
role: 'admin' | 'user';
}
function createUser(user: User) { /* ... */ }
// ❌ Missing 'role' property
createUser({ name: 'Alice', email: 'alice@example.com' });
// ✅ Include all required properties
createUser({ name: 'Alice', email: 'alice@example.com', role: 'user' });
Fix 4: Handle union types properly
function process(input: string | number) {
// ❌ Can't call .toFixed() on string | number
return input.toFixed(2);
// ✅ Narrow the type first
if (typeof input === 'number') {
return input.toFixed(2);
}
return input;
}
Fix 5: Use generics instead of type assertions
// ❌ Forcing with 'as' — hides real bugs
setStatus(someValue as Status);
// ✅ Better: validate at runtime
function isStatus(value: string): value is Status {
return ['success', 'error', 'pending'].includes(value);
}
if (isStatus(someValue)) {
setStatus(someValue); // TypeScript knows it's Status
}
Fix 6: Check function overloads
Some functions have multiple signatures. Make sure you’re matching the right one:
// addEventListener has many overloads
// ❌ Wrong event name type
element.addEventListener('clck', handler);
// ✅ Correct event name
element.addEventListener('click', handler);
Related resources
How to prevent it
- Hover over variables in your IDE to see their inferred types before passing them
- Use
as constfor literal values that should keep their narrow type - Prefer type annotations on variables over type assertions (
as) - Use TypeScript’s
satisfiesoperator to validate types while keeping inference - Read the error message carefully — it tells you exactly which types don’t match