Default Parameters
A default parameter supplies a fallback value that is used whenever the caller omits the argument or passes undefined. Defaults make a parameter optional at the call site while keeping its type non-undefined inside the body — the best of both worlds. This page covers the syntax, how TypeScript infers a default’s type, the difference between defaults and optional parameters, and the subtle interaction between defaults and explicit undefined.
Declaring a default value
Assign a value with = in the parameter list. The caller may then omit that argument, and the default fills in.
function createUser(name: string, role = "member") {
return { name, role };
}
createUser("Ada"); // { name: "Ada", role: "member" }
createUser("Ada", "admin"); // { name: "Ada", role: "admin" }
Crucially, inside the body role has type string, not string | undefined. The default guarantees a value, so you can use it without a guard.
Type inference from the default
When a parameter has a default but no annotation, TypeScript infers its type from the default value. You can still add an explicit annotation when the default is narrower than the type you want to accept.
// `count` inferred as `number`
function repeat(text: string, count = 1) {
return text.repeat(count);
}
// Explicit annotation widens beyond the literal default
function paginate(page: number, size: 10 | 25 | 50 = 10) {
return { page, size };
}
Without the annotation in paginate, size would be inferred as number. The explicit 10 | 25 | 50 keeps the parameter constrained to the allowed page sizes while still defaulting to 10.
Defaults are triggered by undefined
A default kicks in not only when the argument is omitted but also when undefined is passed explicitly. Passing null, by contrast, does not trigger the default — null is a real value.
function volume(level = 50) {
return level;
}
volume(); // 50 (omitted)
volume(undefined); // 50 (undefined triggers the default)
volume(0); // 0 (a real value, default not used)
Pass
undefinedto skip a default in the middle of an argument list. Because a defaulted parameter is treated like an optional one, you can writef(a, undefined, c)to keepb’s default while still supplying later arguments.
Defaults vs. optional parameters
A default parameter is optional at the call site, just like ?, but it changes the type seen inside the function. Use ? when there is no sensible fallback and the body should handle the missing case; use a default when you can provide one.
| Declaration | Caller may omit? | Type inside body | Fallback |
|---|---|---|---|
x?: number | Yes | number | undefined | none |
x = 0 | Yes | number | 0 |
x: number | No | number | n/a |
Note that you cannot combine ? and a default — x?: number = 0 is a syntax error, because a default already implies optionality.
Default ordering and required parameters after
Unlike optional parameters, a defaulted parameter may appear before a required one — but doing so means the caller must pass undefined to use the default. This is rarely worth it; keep defaults at the end.
// Legal but awkward: caller must write fetchData(undefined, "/users")
function fetchData(retries = 3, url: string) {
return { url, retries };
}
// Preferred: required first, defaults last
function fetchDataBetter(url: string, retries = 3) {
return { url, retries };
}
The second form reads naturally and lets callers simply write fetchDataBetter("/users").
Defaults that reference earlier parameters
A default expression can reference parameters declared before it, which is handy for derived fallbacks. It can be any expression, evaluated at call time.
function makeRange(start: number, end: number = start + 10) {
return { start, end };
}
makeRange(5); // { start: 5, end: 15 }
makeRange(5, 8); // { start: 5, end: 8 }
Each default is evaluated fresh on every call, so referencing a mutable value (like Date.now()) gives the current value at invocation time, not at definition time.
Best Practices
- Prefer a default over
?whenever a sensible fallback exists — the body then sees a non-undefinedtype. - Let the default’s type be inferred unless you need to widen it (e.g. to a literal union).
- Remember that
undefinedtriggers a default butnulldoes not. - Keep defaulted parameters at the end so callers can omit them without passing
undefined. - Never combine
?and=; the default already makes the parameter optional. - Use derived defaults (
end = start + 10) sparingly and only when the relationship is obvious. - Move to an options object once several parameters need defaults.