A type parameter can carry a default, just like a function parameter: <T = string>. Defaults make a generic usable without spelling out every argument, but they interact with inference and ordering rules that decide whether callers must pass types explicitly.
Before you start
You should be comfortable with generic functions and constraints. This article covers defaults and ordering; it builds on basic generic syntax.
Step-by-step walkthrough
Step 1: Default the parameter that rarely changes
function createList<T = string>(items: T[]): T[] lets callers write createList(['a']) and get string[] without naming T. Defaults are most useful when one parameter is a sensible common case and the others are inferred from arguments.
Step 2: Order required before defaulted, and inferred before manual
Like function parameters, type parameters with defaults should follow those without. TypeScript also infers left to right, so a parameter that is inferred from an argument should not be blocked by one the caller must supply. Putting a manually specified parameter first is usually the safest order.
Step 3: Reset inference deliberately
A default is used only when the parameter cannot be inferred and is not provided. If the caller passes an argument, inference wins over the default. To force a default anyway, the caller must pass undefined or the type explicitly, so document when the default is the intended behavior.
Worked scenario
The default makes the type argument optional when the array is empty.
interface Result<T = string> {
data: T;
error: string | null;
}
const ok: Result = { data: 'hello', error: null }; // T defaults to string
const count: Result<number> = { data: 1, error: null };
void ok;
void count;Walk through the example
Result without an argument defaults T to string, so data must be a string. Passing Result<number> overrides the default for that use. This is the pattern behind many library types, where the common payload type is the default and callers opt into something else only when needed.
Common mistake
Placing a defaulted parameter before a required one, which forces the required one to also have the same or a later default and produces confusing errors. Another mistake is expecting a default to override an inferred type: if the argument allows inference, the default is ignored.
Verify the behavior
Use the generic without a type argument and confirm the default applies. Pass an explicit type argument and confirm it overrides. Pass a value that infers a different type and confirm inference takes precedence. Finally, declare a defaulted parameter before a required one and read the compiler’s ordering error.
Interview exercise
Should function pair<K, V = string>(key: K, value: V) default V, or should the caller always pass it?
Answer and reasoning
Default V only if a string value is a genuinely common case; otherwise it hides intent and can silently type a value as string when the caller meant a number. Here V is inferred from value, so the default rarely applies — inference wins whenever a value is passed, and pair('a', 1) still infers number. Defaults belong on parameters that are typically not inferable.
Continue learning
Go deeper with generic constraints and const type parameters. Read the TypeScript generics handbook and try the TypeScript MCQs.