🔧 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 null or undefined to 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);

How to prevent it

  • Hover over variables in your IDE to see their inferred types before passing them
  • Use as const for literal values that should keep their narrow type
  • Prefer type annotations on variables over type assertions (as)
  • Use TypeScript’s satisfies operator to validate types while keeping inference
  • Read the error message carefully — it tells you exactly which types don’t match