How to fix Argument of type 'undefined' is not assignable to parameter of type 'string | undefined' in TypeScript

TypeScriptINTERMEDIATEMEDIUMUpdated Dec 8, 2025· 118 views

This TypeScript error occurs when you try to pass a value that might be undefined to a function parameter that doesn't explicitly accept undefined in its type. The fix involves either adding undefined to the parameter type union, using optional parameters, or checking the value before passing it.

Quick fix

Fixes TS2345

function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // returns string | undefined
greet(user); // ERROR: undefined not assignable to string
  1. Add undefined to the parameter's type union
  2. Use a type guard to check the value before passing
  3. Use the non-null assertion operator (!)
  4. Use nullish coalescing (??) to provide a default
typescript — error
function greet(name: string) {
console.log(`Hello, ${name}`);
}
const user = getName(); // returns string | undefined
greet(user); // ERROR: undefined not assignable to string
Argument of type 'undefined' is not assignable to parameter of type 'string | undefined'

What this error means

The error "Argument of type 'undefined' is not assignable to parameter of type 'string | undefined'" occurs when TypeScript's strict null checking detects a type mismatch. This typically happens when: 1. You're passing a variable that might be undefined to a function parameter 2. The parameter's type annotation doesn't include undefined in its union type 3. TypeScript cannot prove that the variable is defined when you call the function When strictNullChecks is enabled (recommended), TypeScript treats undefined and null as distinct types that must be explicitly included in type unions. This prevents runtime errors where you accidentally try to use undefined values as if they were the expected type. The error is TypeScript's way of protecting you from undefined-related runtime bugs. Unlike JavaScript, which silently coerces undefined in many contexts, TypeScript forces you to handle these cases explicitly.

Typical symptoms

  • TypeScript compilation fails with TS2345 error when calling a function
  • IDE shows a red squiggly line under a function argument
  • The error message says 'undefined' cannot be assigned to a type that includes other options
  • Code works at runtime but TypeScript prevents compilation
  • Passing a variable from a condition or optional value causes the error
  • Using values from optional object properties triggers the error
  • Function parameters with no default value cause errors when variables might be undefined

Common causes

  1. The parameter type doesn't include undefined in its union type
  2. You're passing a variable that might be undefined without checking it first
  3. strictNullChecks is enabled in tsconfig.json (which is the correct setting)
  4. The function parameter is required but you're passing an optional value
  5. Using optional chaining (?.) or optional object properties without proper type guards
  6. Destructuring an optional object property and passing it directly
  7. The variable comes from a condition where one branch might not assign a value
  8. Using array find(), optional parameters, or other operations that return undefined

How to fix "Argument of type 'undefined' is not assignable to parameter of type 'string | undefined'"

1Add undefined to the parameter's type union

The most common fix is to explicitly add undefined to the parameter's type annotation if the function is designed to accept undefined:

Before (causes error):

typescript
function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // returns string | undefined
greet(user); // ERROR: undefined not assignable to string

After (fixed):

typescript
function greet(name: string | undefined) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // returns string | undefined
greet(user); // OK - function accepts undefined

Using optional parameters (shorthand):

typescript
// These are equivalent:
function greet(name?: string) { }
function greet(name: string | undefined) { }

// Both allow calling with undefined or omitting the argument
greet(undefined); // OK
greet(); // OK
greet("Alice"); // OK

This is the preferred approach when the function logic can handle undefined values.

2Use a type guard to check the value before passing

If you can't change the function signature, check that the variable is defined before passing it:

Using if statement:

typescript
function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // returns string | undefined

if (user !== undefined) {
  greet(user); // OK - TypeScript knows user is string here
}

Using if with truthy check (for non-empty strings):

typescript
const user = getName();

if (user) { // Also checks for empty strings
  greet(user); // OK
}

Using logical AND operator:

typescript
const user = getName();
user && greet(user); // Executes greet only if user is truthy

Using optional chaining with nullish coalescing:

typescript
const user = getName() ?? "Guest";
greet(user); // OK - user is guaranteed to be string

Type guards help TypeScript narrow the type, proving the value is safe to use.

3Use the non-null assertion operator (!)

If you're certain a value will be defined at runtime, use the ! operator:

Using non-null assertion:

typescript
function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // returns string | undefined
greet(user!); // OK - ! tells TypeScript to trust you

Important: This is a last resort. Only use when you're absolutely certain the variable will be defined:

typescript
// Good use case - you know the DOM element exists
const button = document.getElementById("submit")!;
button.addEventListener("click", () => { });

// Bad use case - you're not sure the value exists
const user = getUserFromAPI();
greet(user!); // May crash at runtime if user is undefined

Warning: The ! operator bypasses TypeScript's safety checks. If you're wrong about the value being defined, your code will crash at runtime. Prefer type guards when possible.

4Use nullish coalescing (??) to provide a default

The nullish coalescing operator (??) provides a fallback value when the original is null or undefined:

Basic example:

typescript
function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // returns string | undefined
greet(user ?? "Guest"); // OK - user is string | undefined, ?? returns string

With object properties:

typescript
interface User {
  name?: string;
}

function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user: User = getUser();
greet(user.name ?? "Anonymous"); // OK

Difference from logical OR (||):

typescript
// || replaces falsy values (0, empty string, false, null, undefined)
const count = getCachedCount() || 0; // "0" becomes 0

// ?? only replaces null/undefined
const count = getCachedCount() ?? 0; // "0" stays "0"

Nullish coalescing is ideal when you want a sensible default and can't change the function.

5Enable strictNullChecks in tsconfig.json

If strictNullChecks is disabled, enable it to get better type safety:

Check your tsconfig.json:

json
{
  "compilerOptions": {
    "strict": true,
    // or explicitly:
    "strictNullChecks": true
  }
}

If you have "strict": true, strictNullChecks is already enabled.

If strictNullChecks is false and you're seeing this error:
It's likely enabled in a different config file, or you're using a build tool that enforces it. Search for other tsconfig files in your project:

bash
find . -name "tsconfig*.json" -type f

Why strict null checks are essential:
- Catches undefined/null errors at compile time, not runtime
- Prevents silent coercions that hide bugs
- Makes your code more explicit and maintainable
- Industry best practice (Next.js, React, Angular all enable it)

Enabling strict checks incrementally:
If you have a large codebase with strictNullChecks disabled, enable it gradually:

1. Set "strictNullChecks": true in tsconfig.json
2. Fix compilation errors in one module at a time
3. Don't disable the flag to ignore errors - address them properly
4. Once all errors are fixed, enjoy the safety benefits

6Use assertion functions for custom type narrowing

For complex scenarios, define assertion functions that tell TypeScript a value is safe:

Basic assertion function:

typescript
function assertDefined<T>(value: T): asserts value is NonNullable<T> {
  if (value === null || value === undefined) {
    throw new Error("Value is null or undefined");
  }
}

function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user = getName(); // string | undefined
assertDefined(user);
greet(user); // OK - TypeScript knows user is string now

Assertion function with custom check:

typescript
function assertIsString(value: unknown): asserts value is string {
  if (typeof value !== "string") {
    throw new Error(`Expected string, got ${typeof value}`);
  }
}

const user: unknown = getUserInput();
assertIsString(user);
greet(user); // OK - user is string

Using a validation library:

typescript
import { z } from "zod";

const UserSchema = z.object({
  name: z.string(),
});

const data = getDataFromAPI(); // unknown
const user = UserSchema.parse(data); // throws if invalid
greet(user.name); // OK - user.name is guaranteed string

Assertion functions are powerful for runtime validation and type narrowing.

7Fix optional property access patterns

When accessing optional properties, handle undefined values explicitly:

Problem with optional properties:

typescript
interface User {
  name?: string;
}

function greet(name: string) {
  console.log(`Hello, ${name}`);
}

const user: User = getUser();
greet(user.name); // ERROR - name might be undefined

Solution 1: Use optional chaining with nullish coalescing:

typescript
const user: User = getUser();
greet(user?.name ?? "Guest"); // OK

Solution 2: Destructure with defaults:

typescript
const { name = "Guest" } = getUser();
greet(name); // OK - name is guaranteed string

Solution 3: Use optional parameter in function:

typescript
function greet(name?: string) {
  console.log(`Hello, ${name ?? "Guest"}`);
}

const user: User = getUser();
greet(user.name); // OK - function accepts undefined

Solution 4: Update interface if property should always exist:

typescript
interface User {
  name: string; // Remove ? - name is required
}

const user: User = getUser();
greet(user.name); // OK - guaranteed to exist

Choose the solution based on whether the property should truly be optional.

Advanced notes

strictNullChecks: The Foundation of TypeScript Safety

When strictNullChecks is enabled, null and undefined stop being assignable to all types. This is the correct default behavior and aligns with JavaScript semantics where accessing undefined is a runtime error.

Why this is important:
In JavaScript, many operations return undefined implicitly (missing return statements, undefined object properties, missing array elements). TypeScript's strict null checks force you to handle these cases explicitly, catching bugs before they reach production.

Type Narrowing Patterns:

TypeScript understands several patterns that narrow types:

1. Truthiness checks:

typescript
const value: string | undefined = getValue();
if (value) {
  // value is string here (not empty)
}

2. Explicit undefined checks:

typescript
if (value !== undefined) {
  // value is string here
}

3. Logical operators:

typescript
const safe = value && procesString(value); // safe only if value is truthy
const withDefault = value || "default"; // string

4. Optional chaining:

typescript
const length = value?.length; // undefined if value is undefined

5. Nullish coalescing:

typescript
const result = value ?? fallback; // Uses fallback only for null/undefined

Union Types in Function Parameters:

When a function parameter has a union type, it can accept any type in the union:

typescript
function process(value: string | number | undefined) {
  // Can be any of the three types
}

process("hello"); // OK
process(42); // OK
process(undefined); // OK
process(null); // ERROR - null not in union

Common Patterns:

1. Optional parameters:

typescript
function configure(debug?: boolean) { } // boolean | undefined
configure(); // OK
configure(true); // OK
configure(undefined); // OK

2. Null or undefined (classic):

typescript
function setup(config: Config | null | undefined) { }

3. Required with default in caller:

typescript
function greet(name: string) { } // Required

const user = getUserOrDefault(); // Returns string (never undefined)
greet(user); // OK

Interoperability with Untyped Code:

When working with JavaScript libraries or untyped code, you may need to assert types:

typescript
// From untyped library
const result: any = externalLibrary.getData();

// Option 1: Type assertion
const data = result as string;

// Option 2: Validate first
if (typeof result === "string") {
  process(result);
}

// Option 3: Use a schema library
const data = parseWith(MySchema, result);

Performance Considerations:

Strict null checking has no runtime performance impact - it's purely a compile-time feature. Type narrowing is also compile-time only; the generated JavaScript doesn't reflect narrowing.

Migration to Strict Null Checks:

If adding this to a legacy codebase:

1. Set "strictNullChecks": true in tsconfig.json
2. Run tsc to see all violations
3. Fix errors systematically (don't disable the flag)
4. Use assertion functions and guards to narrow types
5. Update function signatures to be explicit about nullable parameters
6. Add tests for null/undefined cases

Related TypeScript Errors:

- TS2532: Object is possibly undefined - accessing properties
- TS2531: Object is possibly null or undefined - similar to TS2345
- TS2349: Cannot invoke optional method - calling functions that might be undefined
- TS7053: Element implicitly has unknown type - accessing with potentially undefined keys

Frequently asked questions

What does "TS2345" mean?
The error "Argument of type 'undefined' is not assignable to parameter of type 'string | undefined'" occurs when TypeScript's strict null checking detects a type mismatch. This typically happens when: 1. You're passing a variable that might be undefined to a function parameter 2.
How do I fix "TS2345"?
This TypeScript error occurs when you try to pass a value that might be undefined to a function parameter that doesn't explicitly accept undefined in its type. The fix involves either adding undefined to the parameter type union, using optional parameters, or checking the value before passing it.
What causes "TS2345"?
The parameter type doesn't include undefined in its union type You're passing a variable that might be undefined without checking it first strictNullChecks is enabled in tsconfig.json (which is the correct setting)
Is the "TS2345" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading