Chapter 2.2โ˜• 13 min read

Optional & Default Parameters

Not every argument needs to show up every time.

01Chai & Extras

In JavaScript, if you call a function without passing an argument, that parameter simply becomes undefined. TypeScript takes this a step further and gives you two explicit, type-safe ways to handle missing arguments: Optional Parameters and Default Parameters.

Optional parameters let the caller skip the argument entirely, and the value inside the function becomes undefined. Default parameters also let the caller skip the argument, but instead of undefined, the parameter gets a fallback value that you define.

Think of it like ordering Irani chai at Nimrah Cafe near Charminar. The chai itself is required โ€” you can't go to the counter and order "nothing." That's your required parameter. But the extras are optional: saying "Bhai, chai do" is perfectly fine on its own. If you want, you can add "maska" or "osmania biscuit" โ€” those are optional parameters. You don't have to say them, but you can.

And default parameters? That's like when you order chai and they automatically make it with sugar. You didn't explicitly ask for sugar, but it's there by default. However, if you say "bina sugar" (without sugar), you're overriding that default. This is exactly how default parameters work in TypeScript โ€” you get a standard value unless you explicitly say otherwise.

This flexibility makes your functions much more expressive and easier to use. Callers only need to provide what they care about, and the function handles the rest gracefully.

02Optional Parameters

You mark a parameter as optional by adding a ? question mark after its name. This tells TypeScript: "The caller might not provide this argument, and that's okay."

function greet(name: string, title?: string): string {
  if (title !== undefined) {
    return `${title} ${name}`;
  }
  return `Hello ${name}`;
}

greet("Imran");       // โœ… "Hello Imran" (title is undefined)
greet("Imran", "Mr."); // โœ… "Mr. Imran"

When you skip an optional parameter, its value inside the function is undefined. You must check for undefined before using it, or your code might crash. You can check with a simple if, or use the nullish coalescing operator ??:

function greet(name: string, title?: string): string {
  const displayTitle = title ?? "Friend";
  return `Hello ${displayTitle} ${name}`;
}

There is one critical rule: Optional parameters must come AFTER required parameters. You cannot put an optional parameter before a required one.

// โŒ ERROR: Required parameter follows optional parameter
function greet(title?: string, name: string): string { ... }

// โœ… Correct order: required first, optional last
function greet(name: string, title?: string): string { ... }

Think of it like the biryani serving line at a wedding. The main biryani is required โ€” you must take it. The raita and shorba are optional extras at the end. If you put the optional extras before the required main dish, the whole line gets confused and stops. TypeScript enforces this same logical ordering for your function parameters.

The function type signature also reflects the optional parameter: (name: string, title?: string) => string. The type system knows that both greet("Imran") and greet("Imran", "Mr.") are valid call forms.

03Default Parameters

Default parameters let you assign a fallback value directly in the function declaration using the = sign. If the caller skips the argument, the parameter gets that default value instead of undefined.

function greet(name: string, greeting: string = "Hello"): string {
  return `${greeting}, ${name}!`;
}

greet("Imran");        // โœ… "Hello, Imran!" (greeting defaults to "Hello")
greet("Imran", "Salam"); // โœ… "Salam, Imran!" (greeting is overridden)

The key difference from optional parameters is that default parameters are never undefined inside the function โ€” they always have a concrete value, either from the caller or from the default. This means you don't need to write if (greeting !== undefined) checks.

Another advantage: unlike optional parameters, default parameters can come before required parameters. However, if you put a default parameter before a required one, you must explicitly pass undefined to use the default value:

function create(name: string = "Guest", role: string): object {
  return { name, role };
}

create(undefined, "admin"); // โœ… name is "Guest", role is "admin"
create("Imran", "admin");   // โœ… name is "Imran", role is "admin"

TypeScript is smart enough to infer the type from the default value. If you write function f(count = 10), TypeScript automatically knows count is number. You don't need to write count: number = 10, though you can for extra clarity.

// Real-world examples
function fetch(url: string, timeout: number = 5000) { ... }
function formatCurrency(amount: number, currency: string = "INR", locale: string = "en-IN") { ... }

It's like ordering at an auto stand โ€” the default destination might be "Secunderabad Station," but you can always tell the driver "Charminar" to override it. The default keeps things moving when you don't have a specific preference.

04The Gotchas

While optional and default parameters are incredibly useful, they come with a few traps that catch developers off guard, especially in interviews.

Trap 1: Optional vs Default Type Difference. function f(x?: number) means x is number | undefined inside the function. But function f(x: number = 0) means x is just number. With optional, you MUST check for undefined. With default, you don't. This is a crucial distinction for the function body!

function optional(x?: number) {
  console.log(x.toFixed(2)); // โŒ ERROR: x might be undefined
}

function defaulted(x: number = 0) {
  console.log(x.toFixed(2)); // โœ… SAFE: x is always a number
}

Trap 2: Optional parameter in the middle. function f(a: string, b?: number, c: string) is an ERROR. All optional parameters must be at the end. But function f(a: string, b: number = 5, c: string) is VALID because default parameters can appear anywhere. You'd call it with f("hello", undefined, "world") to skip b and use its default.

Trap 3: Overriding defaults with wrong types. If you have function f(count: number = 10) and call f("twenty"), TypeScript catches this error immediately. But calling f(undefined) works perfectly and uses the default value.

Trap 4: The null vs undefined trick. This one sneaks up on everyone! Passing undefined as an argument uses the default value, but passing null does NOT. null is treated as a valid, intentional value, not as "missing."

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

greet(undefined); // "Hello, Guest!" (uses default)
greet(null);      // "Hello, null!" (null overrides the default!)

Seedha samjho โ€” null is like telling the Irani chai guy "bina sugar" โ€” it's an explicit instruction. undefined is like saying nothing at all, so he adds the default sugar.

05Optional & Default Cheatsheet

Let's lock this in with a side-by-side cheatsheet of optional and default parameters. This is your quick reference for deciding which one to use and how they behave.

Comparison Table

FeatureOptional (?)Default (=)
Syntaxtitle?: stringgreeting: string = "Hello"
Value when skippedundefinedThe default value
Type inside functionstring | undefinedstring (never undefined)
Must check for undefined?โœ… YesโŒ No
Position ruleMUST be at the endCan be anywhere
Skipping a middle one?โŒ Not possibleโœ… Pass undefined

Calling Patterns

// Skipping optional
greet("Imran");               // title is undefined

// Overriding default
greet("Imran", "Hey");        // greeting is "Hey" instead of "Hello"

// Skipping a middle default parameter
create("hello", undefined, "world"); // Uses default for 2nd param

Type Inference

function f(count = 10) {
  // TypeScript infers 'count' as 'number', NOT 'number | undefined'
  // You don't need: function f(count: number = 10)
}

The Golden Rule

"Use optional when undefined is a meaningful value that you want to check for. Use default when you want a fallback value so you never have to deal with undefined. Never put optional parameters before required ones."

Think of it this way: Optional is like the "extra mirchi" option on your biryani โ€” sometimes you want it, sometimes you don't, and the chef needs to check if you asked for it. Default is like the standard salan that comes with every biryani order โ€” it's always there unless you specifically say "bina salan." Choose the tool that matches your intent!

Key Takeaways

  • Optional parameters use ? and become undefined when skipped โ€” they must go at the end
  • Default parameters use = and get a fallback value when skipped โ€” they can go anywhere
  • Optional parameters have type T | undefined inside the function; default parameters have type T
  • You must check for undefined when using optional parameters, but not with defaults
  • Passing undefined to a default parameter uses the default value, but passing null does NOT
  • Golden rule: Use optional when undefined is meaningful, default when you want a fallback
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase