Default Type Arguments

`<T = Default>` — When Callers Don't Provide One

Default Type Arguments

Type parameters can have defaults. Useful when most callers want the same thing — they can omit it.

3 min read Level 2/5 #typescript#generics#defaults
What you'll learn
  • Add defaults to generic parameters
  • Order parameters with defaults at the end

A type parameter can have a default — used when the caller doesn’t supply one and TS can’t infer it.

The Syntax

type Container<T = string> = {
  items: T[];
};

const a: Container = { items: ["a", "b"] };               // T = string (default)
const b: Container<number> = { items: [1, 2, 3] };        // T = number

Why It Matters

Without a default, you’d always have to specify:

const a: Container<string> = { items: ["a", "b"] };
//                  ^^^^^^^ verbose; most callers want this

Default narrows the common case.

Defaults With Constraints

type Result<T = unknown, E extends Error = Error> = {
  data?: T;
  error?: E;
};

const r: Result = { data: { name: "Ada" } };   // both defaults used

You can combine extends X = Y for “must be assignable to X, defaults to Y”.

Order Matters

Defaults must come AFTER required parameters:

type Wrong<T = string, U> = ...;
//          ~~~~~~~~~~  Type parameter 'U' has a default but follows a required parameter

type Right<T, U = string> = ...;

Same rule as function parameters.

A Real Example — React 18 hooks

function useState<T = undefined>(initial?: T): [T, (v: T) => void] {
  // ...
}

useState();              // T = undefined
useState("hello");        // T = string
useState<number>();       // T = number, explicit

The default lets callers use the hook even when nothing’s inferable.

Up Next

Generics on classes.

Generic Classes →