How to Use Default Parameter Values in TypeScript?

Default parameters in TypeScript let you define fallback values for function arguments so your code behaves predictably even when some callers omit certain arguments. In real-world applications, such as API wrappers, UI handlers, and business logic services, good defaults make your functions easier to use, safer to refactor, and more self-documenting.

What Are Default Parameters in TypeScript?

Default parameters allow you to assign a default value to a function parameter. If the function is called without a value for that parameter, or with undefined, the default value is used.

This is especially useful when:

  • You want to make a parameter optional for most callers
  • You want your function to always have a usable value at runtime
  • You want to avoid repetitive if (!param) { … } checks inside the function body

Example idea:

  • A logging function that defaults to “info” level
  • A discount function with a default discount rate
  • A greeting function that defaults to “Guest”

Syntax of Default Parameters

The syntax for default parameters is straightforward: assign a value in the function declaration.

function functionName(parameter: type = defaultValue) {
// function body
}

You can define multiple parameters, with some or all of them having defaults:

function createUser(
name: string,
isActive: boolean = true,
role: "user" | "admin" = "user"
) {
return { name, isActive, role };
}

const user1 = createUser("Alice"); // isActive = true, role = "user"
const user2 = createUser("Bob", false, "admin");

Default parameters also work with arrow functions, which is very common in modern TypeScript projects:

const logEvent = (event: string, level: "info" | "error" = "info") => {
console.log(`[${level}] ${event}`);
};

logEvent("App started"); // [info] App started
logEvent("App failed", "error"); // [error] App failed

Important rule: Default parameters typically come after required parameters. This makes calling the function simpler and avoids confusing parameter ordering.

Default Parameters vs Optional Parameters

TypeScript also supports optional parameters using ?, for example parameter?: type. It’s important to understand how this differs from default parameters.

Optional parameters

function sendEmail(
to: string,
subject: string,
body?: string
) {
// body can be string or undefined
}
  • body may be undefined
  • There is no default value; callers decide whether to provide this argument
  • You often need to handle the undefined case inside the function

Default parameters

function sendEmailWithDefaultBody(
to: string,
subject: string,
body: string = "No message provided"
) {
// body is always a string at runtime
}
  • body always has a value at runtime
  • When the caller omits the argument or passes undefined, the default is applied
  • Callers don’t need to think about a “no message” case if the default is acceptable

When to use what:

  • Use optional parameters when the absence of a value (undefined) has meaning in your logic
  • Use default parameters when you always want a usable runtime value, and a sensible default exists

Example 1: Greeting Function with a Default Name

Let’s start with a simple greeting function that uses a default name when no value is provided.

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

// Calling the function without an argument
greet();
// Output: Hello, Guest! Welcome to our application.

// Calling the function with an argument
greet("John");
// Output: Hello, John! Welcome to our application.

I executed the above example code and added the screenshot below.

Default Parameter Values in TypeScript

This pattern is cleaner than writing:

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

Using a default parameter moves the defaulting logic into the function signature, making the API more self-documenting.

Example 2: Calculate Discounts with Default Rate

Here’s a more practical example from e-commerce or billing scenarios. Suppose you want to calculate the final price after applying a discount, but when no discount rate is passed, you want to default to 10%.

function calculateDiscount(
price: number,
discountRate: number = 0.1
): number {
return price - price * discountRate;
}

// Calling the function without a discount rate
console.log(calculateDiscount(100));
// Output: 90

// Calling the function with a discount rate
console.log(calculateDiscount(100, 0.2));
// Output: 80

I executed the above example code and added the screenshot below.

Use Default Parameter Values in TypeScript

In real-world projects, you often prefer an options object instead of long parameter lists. You can combine options with defaults like this:

interface DiscountOptions {
rate?: number;
}

function calculateDiscountWithOptions(
price: number,
options: DiscountOptions = {}
): number {
const rate = options.rate ?? 0.1;
return price - price * rate;
}

console.log(calculateDiscountWithOptions(100)); // 90
console.log(calculateDiscountWithOptions(100, { rate: 0.2 })); // 80

This pattern scales better as you add more configuration (e.g., discount type, currency, rounding strategy).

Example 3: Fetch User Data with a Default User ID

In many applications, you need to fetch user data, sometimes falling

user (like a demo user or a system account).

interface User {
id: string;
name: string;
}

async function fetchUserData(
userId: string = "defaultUser"
): Promise<User> {
console.log(`Fetching data for user: ${userId}`);

// Simulated fetch logic
// In real code, you might call fetch/axios here
return {
id: userId,
name: userId === "defaultUser" ? "Default User" : "Sample User"
};
}

// Calling the function without a user ID
fetchUserData().then(user => console.log(user));
// Fetching data for user: defaultUser

// Calling the function with a user ID
fetchUserData("user123").then(user => console.log(user));
// Fetching data for user: user123

I executed the above example code and added the screenshot below.

How to Use Default Parameter Values in TypeScript

In a production system, consider whether a hard-coded default user is appropriate. For sensitive operations, it might be better to require callers to explicitly provide a user ID or to inject a default via configuration.

How Default Parameters Handle undefined and null

A subtle but important detail is how default parameters behave with undefined and null.

  • Default parameters are applied when the argument is undefined or omitted
  • Default parameters are not applied when the argument is null or any other value

Consider this example:

function logValue(value: string = "default") {
console.log(value);
}

logValue(); // "default"
logValue(undefined as any); // "default"
logValue("Hello"); // "Hello"
logValue(null as any); // "null"

Key points:

  • Calling logValue() or logValue(undefined) will use the default “default”
  • Passing null is treated as a normal value at runtime, so the default is not applied
  • With strictNullChecks enabled, you typically model null and undefined explicitly in the type if you need both

Design your APIs so that callers understand whether they should pass undefined, null, or nothing at all. Mixing all three without a clear convention can quickly become confusing.

Real-World Pattern: Default Parameters in UI Handlers

In frontend applications (React, Angular, Vue), default parameters are often used in event handlers and helper functions.

type Theme = "light" | "dark";

function applyTheme(theme: Theme = "light") {
// Apply the selected theme
console.log(`Applying theme: ${theme}`);
}

// In a click handler, you might call:
applyTheme(); // light theme
applyTheme("dark"); // dark theme

This is helpful when you have multiple controls or routes that rely on the same function but do not always specify a theme explicitly.

Another example is a pagination helper:

interface FetchPageOptions {
page?: number;
pageSize?: number;
}

function fetchPage(
resource: string,
{ page = 1, pageSize = 20 }: FetchPageOptions = {}
) {
console.log(`Fetching ${resource}, page ${page}, size ${pageSize}`);
}

fetchPage("orders"); // page 1, size 20
fetchPage("orders", { page: 2 }); // page 2, size 20
fetchPage("orders", { pageSize: 50 }); // page 1, size 50

Here, defaults are applied via destructuring, giving you clean, expressive function signatures.

When You Should Avoid Default Parameters

Default parameters are powerful, but they are not always the right choice. Overusing them can hide bugs or create confusing APIs.

Avoid default parameters when:

  • The default value is expensive to compute
    • In such cases, compute the value lazily inside the function only when needed
  • The default depends on dynamic context (for example, current user, request context, tenant)
    • Use dependency injection or pass a context object instead
  • Defaulting an object might hide missing data
    • Automatically defaulting to {} can hide bugs where callers forget to pass the required configuration

Example anti-pattern:

// Anti-pattern: silently defaulting to an empty config
interface Config {
featureFlag: boolean;
}

function initializeFeature(config: Config = { featureFlag: false }) {
// If caller forgets to pass config, you might silently disable a feature
console.log(config.featureFlag);
}

A better design might force callers to pass the configuration or use a clearly named factory:

function createDefaultConfig(): Config {
return { featureFlag: false };
}

function initializeFeature(config: Config) {
console.log(config.featureFlag);
}

initializeFeature(createDefaultConfig());

This makes the defaulting logic explicit and easier to reason about when debugging.\

Hands-On Exercises

If you want to reinforce your understanding, try these small exercises:

  1. Logging with default level
    • Write a logMessage function that takes message: string and level: “info” | “warn” | “error”, with “info” as the default level.
    • Call it with and without the level parameter.
  2. Report generator
    • Create a generateReport function that takes title: string, includeDate: boolean (default true), and format: “pdf” | “html” (default “pdf”).
    • Print different messages based on the arguments.
  3. Options object with defaults
    • Define an EmailOptions interface with from?cc?bcc?.
    • Create a sendEmailWithOptions(to: string, subject: string, options?: EmailOptions) function that applies sensible defaults using destructuring and default values.

Try implementing each exercise with both optional and default parameters to see which style feels clearer in each case.

Conclusion

Default parameter values in TypeScript are a simple feature that can dramatically improve the usability and readability of your functions. By choosing sensible defaults, you reduce boilerplate, make your APIs easier to call, and keep business logic focused on what really matters instead of argument validation.

Use default parameters when a clear, safe fallback exists, and reserve optional parameters or explicit configuration objects for cases where the absence of a value carries meaning. With the patterns in this guide, you can design TypeScript functions that are both developer-friendly and robust in production.

You may also like to read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.