Question
Given the following TypeScript interface:
export interface INotificationService {
error(message: string, title?: string, autoHideAfter?: number): void;
}
How can error() be called so that title is not provided, but autoHideAfter is set to 1000?
Short Answer
By the end of this page, you will understand how optional parameters work in TypeScript, why you cannot skip a middle positional argument directly, and the common ways to solve this problem, especially by passing undefined or by redesigning the function to use an options object.
Concept
In TypeScript, function parameters are usually positional. That means arguments are matched by their place in the parameter list:
error(message, title, autoHideAfter)
So even if title is optional, the third argument still belongs to the third position. You cannot jump over the second parameter unless you explicitly put something in that slot.
For this function:
error(message: string, title?: string, autoHideAfter?: number): void;
TypeScript reads the arguments like this:
- first argument →
message - second argument →
title - third argument →
autoHideAfter
If you want to provide autoHideAfter but not title, you need to keep the second position empty in a valid way. The normal solution is:
error("Something went wrong", undefined, 1000);
Mental Model
Think of function parameters like labeled seats in a row:
- Seat 1 =
message - Seat 2 =
title - Seat 3 =
autoHideAfter
If you want to put someone in Seat 3, you still have to acknowledge Seat 2. You cannot magically skip over it. Using undefined is like saying:
“Seat 2 is intentionally empty, and Seat 3 should get this value.”
An options object is like replacing numbered seats with name tags, so you can fill only the fields you want.
Syntax and Examples
The direct call for this signature is:
error("Something went wrong", undefined, 1000);
Example with the interface
interface INotificationService {
error(message: string, title?: string, autoHideAfter?: number): void;
}
const notificationService: INotificationService = {
error(message, title, autoHideAfter) {
console.log({ message, title, autoHideAfter });
}
};
notificationService.error("Save failed", undefined, 1000);
Output:
{
message: "Save failed",
title: undefined,
autoHideAfter: 1000
}
Why this is needed
This does work as intended:
Step by Step Execution
Consider this call:
notificationService.error("Network error", undefined, 1000);
Here is what happens step by step:
"Network error"is passed intomessage.undefinedis passed intotitle.1000is passed intoautoHideAfter.
So inside the function, the values are:
message = "Network error"
title = undefined
autoHideAfter = 1000
Traceable example
function error(message: string, title?: string, autoHideAfter?: number): void {
console.log("message:", message);
.(, title);
.(, autoHideAfter);
}
(, , );
Real World Use Cases
Optional parameters appear often in real applications:
- Notifications and toasts
- message text is required
- title, timeout, or severity may be optional
- Logging utilities
- required log message
- optional tag, metadata, or timestamp override
- HTTP helper functions
- required URL
- optional headers, timeout, retries
- UI dialog helpers
- required content
- optional title, size, closable flag
- Data formatting functions
- required value
- optional locale, precision, currency symbol
In all these cases, too many optional positional parameters can make calls unclear. That is why object parameters are common in production code.
Real Codebase Usage
In real codebases, developers usually handle this in one of two ways.
1. Pass undefined for skipped optional positional arguments
This is common when:
- the API already exists
- you cannot change the function signature
- there are only a few parameters
Example:
notificationService.error("Login failed", undefined, 3000);
2. Use an options object
This is preferred when:
- there are multiple optional settings
- readability matters
- the API may grow over time
Example:
notificationService.error("Login failed", {
autoHideAfter: 3000
});
Common patterns in real projects
Validation
function error(message: string, title?: string, autoHideAfter?: number) {
(!message) {
();
}
}
Common Mistakes
1. Trying to skip a middle argument without undefined
Broken code:
error("Problem", 1000);
Why it fails:
1000is passed astitle- but
titleshould be a string
Fix:
error("Problem", undefined, 1000);
2. Assuming optional means named
Some beginners think this is allowed:
error("Problem", autoHideAfter: 1000);
This is not valid TypeScript function call syntax. Function arguments are positional unless the function accepts an object.
3. Using null without checking API expectations
This may compile depending on your settings, but it means something different from undefined in many codebases:
Comparisons
| Approach | Example | Pros | Cons |
|---|---|---|---|
| Optional positional parameters | error("Failed", undefined, 1000) | Simple for small APIs | Hard to read when skipping values |
| Options object | error("Failed", { autoHideAfter: 1000 }) | Clear, flexible, scalable | Slightly more verbose |
| Overloaded signatures | Multiple function definitions | Can improve type safety for common call shapes | More complex to maintain |
Positional parameters vs options object
Positional
error("Failed", "Warning", 1000);
Best when:
- there are very few parameters
- order is obvious
Cheat Sheet
function error(message: string, title?: string, autoHideAfter?: number): void {}
To skip title and set autoHideAfter
error("Message", undefined, 1000);
Key rules
- TypeScript function arguments are positional.
- Optional parameters can be omitted only from the end naturally.
- To skip an earlier optional argument and provide a later one, pass
undefined. - If the API has many optional values, prefer an options object.
Common pattern
type Options = {
title?: string;
autoHideAfter?: number;
};
function error(message: string, ?: ): {}
FAQ
Can I skip an optional parameter in TypeScript without passing anything?
Only if it is at the end of the argument list. You cannot skip a middle positional parameter unless you pass undefined.
How do I pass the third argument without the second in TypeScript?
Pass undefined for the second argument:
error("Message", undefined, 1000);
Why does error("Message", 1000) fail?
Because TypeScript treats 1000 as the second argument, which maps to title, and title is expected to be a string.
Is null the same as undefined for optional parameters?
Not exactly. undefined usually means “not provided,” while null often means “intentionally empty.” Use undefined when skipping an optional argument.
What is the best way to handle many optional parameters?
Use an options object. It makes function calls clearer and easier to maintain.
Mini Project
Description
Build a small notification helper that shows how optional positional parameters behave and how an options-object redesign can make function calls clearer. This project demonstrates both the direct undefined approach and the more maintainable object-based approach.
Goal
Create a notification service that can display an error message, optionally include a title, and optionally set an auto-hide timeout.
Requirements
- Create a function that accepts
message, optionaltitle, and optionalautoHideAfter. - Call the function once with only a message and once with
autoHideAfterwhile skippingtitle. - Create a second version that uses an options object instead of multiple optional positional parameters.
- Log the received values so the parameter mapping is easy to see.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular Dependency Injection: Fix "Can't Resolve All Parameters for Component" Errors
Learn why Angular shows "Can't resolve all parameters for component" and how to fix service injection issues in components.