Optional Parameters
In JavaScript every parameter is implicitly optional — omitted arguments simply become undefined. TypeScript makes that intent explicit with the ? modifier, which marks a parameter as optional and folds undefined into its type. This page explains how to declare optional parameters, the ordering rules the compiler enforces, how optionality differs from a T | undefined type, and how narrowing lets you use the value safely.
Declaring an optional parameter
Append ? to a parameter name to make it optional. Callers may then omit that argument entirely, and inside the function the parameter has type T | undefined.
function greet(name: string, greeting?: string): string {
return `${greeting ?? "Hello"}, ${name}`;
}
greet("Ada"); // ✅ "Hello, Ada"
greet("Ada", "Welcome"); // ✅ "Welcome, Ada"
Because greeting may be missing, its type inside the body is string | undefined. The ?? (nullish coalescing) operator supplies a fallback only when the value is null or undefined.
Optional parameters must come last
Required parameters cannot follow optional ones — there would be no unambiguous way to map positional arguments. The compiler rejects an optional parameter that precedes a required one.
// ❌ Error: A required parameter cannot follow an optional parameter.
function badRange(start?: number, end: number) {
return [start, end];
}
// ✅ Required first, optional after
function range(start: number, end?: number) {
return end === undefined ? [0, start] : [start, end];
}
If you need a “hole” in the middle, accept undefined explicitly for that position (see the comparison below) or restructure the arguments into an options object.
Optional parameter vs. T | undefined
An optional parameter (x?: T) and a parameter typed as x: T | undefined are not the same. The optional form lets the caller omit the argument; the union form requires the argument to be present, even if its value is undefined.
function optional(x?: number) {}
function explicit(x: number | undefined) {}
optional(); // ✅ may be omitted
explicit(); // ❌ Error: Expected 1 argument, but got 0
explicit(undefined); // ✅ must be passed explicitly
| Declaration | Caller may omit? | Type inside body |
|---|---|---|
x?: number | Yes | number | undefined |
x: number | undefined | No | number | undefined |
x = 0 (default) | Yes | number |
Use
?when omitting the argument is a legitimate call, andT \| undefinedwhen the slot is mandatory but may hold no value. For middle “holes”, the explicit-undefinedform is the only option since optional parameters must be last.
Narrowing the value before use
Since an optional parameter may be undefined, the compiler forces you to handle that case before treating it as the underlying type. A typeof check, an === undefined comparison, or the ??/?. operators all narrow it.
function formatPrice(amount: number, currency?: string): string {
if (currency === undefined) {
return amount.toFixed(2);
}
// `currency` is now `string`
return `${currency} ${amount.toFixed(2)}`;
}
Inside the if, currency is undefined; after it, the compiler narrows it to string. This flow analysis is what makes optional parameters safe to consume.
Optional parameters in callbacks
A function type with an optional parameter accepts an implementation that ignores it — fewer parameters are always assignable to more. This mirrors how Array.prototype.map passes index and array that most callbacks never use.
type Visitor = (value: string, index?: number) => void;
const log: Visitor = (value) => console.log(value); // ✅ ignores index
["a", "b"].map((value) => value.toUpperCase()); // index/array unused
This assignability rule means you rarely need to declare every parameter in your callbacks — declare only the ones you use.
Best Practices
- Use
?for arguments the caller may legitimately leave out. - Keep all optional parameters after the required ones.
- Reach for a default value instead of
?when you have a sensible fallback, so the body sees a non-undefinedtype. - Use
T | undefined(not?) when the argument must be passed but may hold no value, or for middle “holes”. - Narrow optional parameters with
===,typeof,??, or?.before using them. - Prefer an options object once a function accumulates several optional parameters.
- Declare only the callback parameters you actually use; extra trailing parameters are optional by assignability.