How to Set & Use TypeScript Default Parameters
Default parameters in TypeScript are useful for making code more flexible and readable. By assigning default values to function parameters, you can simplify your code, reducing the need for multiple overloads or complex conditions. This article will explore how to use default parameters effectively in TypeScript functions, covering key topics such as setting default parameters, working with optional parameters, and keeping existing code compatible.
Setting Default Parameters in TypeScript Functions
To assign a default value to a parameter in a TypeScript function, use the syntax parameterName: type = defaultValue
. Here's an example:
function greet(name: string = 'World') {
console.log(`Hello, ${name}!`);
}
greet(); // Outputs: "Hello, World!"
greet('John'); // Outputs: "Hello, John!"
This simple feature lets you specify fallback values for function parameters, making your code more adaptable while reducing unnecessary complexity. When working with TypeScript function types, you'll find default parameters especially useful for handling common cases without extra code.
Default parameters in Convex can similarly help when defining backend functions by providing sensible defaults that improve both clarity and flexibility.
Handling Optional Parameters with Default Values
You can combine optional parameters with default values to create versatile functions. Consider this example:
function configureProfile(username: string, email: string, theme?: string, notifications: boolean = true) {
console.log(`Username: ${username}, Email: ${email}, Theme: ${theme}, Notifications: ${notifications}`);
}
configureProfile('johnDoe', 'johndoe@example.com'); // Outputs: "Username: johnDoe, Email: johndoe@example.com, Theme: undefined, Notifications: true"
configureProfile('janeDoe', 'janedoe@example.com', 'dark', false); // Outputs: "Username: janeDoe, Email: janedoe@example.com, Theme: dark, Notifications: false"
Using default values for optional parameters allows you to create functions that are both flexible and straightforward.
This pattern works well when building custom functions in Convex backends, where you often need to handle various input combinations while maintaining type safety.
Defining Functions with Default Arguments
To define a function with default arguments, use the same syntax as setting default parameters. Here's an example:
function sum(a: number = 0, b: number = 0) {
return a + b;
}
console.log(sum()); // Outputs: 0
console.log(sum(5)); // Outputs: 5
console.log(sum(5, 10)); // Outputs: 15
This feature enables you to create functions that can be called with various numbers of arguments, making your code more versatile and reusable. When working with arrow functions in TypeScript, you can apply the same default parameter pattern:
const multiply = (a: number = 1, b: number = 1) => a * b;
For building full-stack TypeScript apps, these patterns help create well-typed backend functions that gracefully handle missing parameters.
Ensuring Backward Compatibility with Default Parameters
When adding new parameters to existing functions, default parameters help maintain compatibility with older code. Consider this example:
// Existing function
function calculateArea(width: number, height: number) {
return width * height;
}
// Updated function with default parameter
function calculateAreaUpdated(width: number, height: number, unit: string = 'square meters') {
const area = width * height;
return `${area} ${unit}`;
}
console.log(calculateAreaUpdated(5, 10)); // Outputs: "50 square meters"
console.log(calculateAreaUpdated(5, 10, 'sq ft')); // Outputs: "50 sq ft"
Default parameters let you enhance existing functions without disrupting previous code. When working with TypeScript interfaces or in larger codebases, this becomes crucial for smooth version upgrades.
This approach is similar to how Convex handles schema evolution, where backward compatibility is maintained while adding new fields and capabilities.
Using Default Parameter Values Effectively
Here are some best practices for using default parameter values:
- Use default parameters for optional settings or configurations.
- Avoid using default parameters for essential or critical settings.
- Keep default values simple and meaningful.
Here's an example:
function createLogger(logLevel: string = 'info', enableConsole: boolean = true) {
// Implementation details...
return {
log: (message: string) => {
if (enableConsole) {
console.log(`[${logLevel}] ${message}`);
}
}
};
}
const logger = createLogger(); // Uses defaults: 'info' level and console enabled
const debugLogger = createLogger('debug'); // Overrides log level, keeps console enabled
const silentLogger = createLogger('error', false); // Custom log level, console disabled
When working with function return types in TypeScript, default parameters can make your APIs more intuitive while preserving type safety.
The Convex types cookbook offers similar patterns for creating flexible, type-safe backend functions that handle various input combinations gracefully.
Specifying Default Values for Function Parameters
When defining default values for function parameters, consider this example:
function createUser(
name: string,
role: string = 'Member',
isActive: boolean = true,
preferences: object = { theme: 'light', notifications: true }
) {
return { name, role, isActive, preferences };
}
// Basic usage with just a name
const newUser = createUser('Jane');
// Override the default role
const adminUser = createUser('John', 'Admin');
// Specify all parameters
const customUser = createUser('Alex', 'Editor', false, { theme: 'dark', notifications: false });
This pattern works well with TypeScript object types, allowing you to create flexible APIs while maintaining type safety. The default values make your functions easier to use while reducing repetitive code.
Similar patterns help create interfaces that are both powerful and developer-friendly when building with Convex.
Applying Default Parameters for Cleaner Code
Using default parameters helps streamline your TypeScript code by eliminating repetitive logic. Consider this example:
// Without default parameters
function fetchData(endpoint: string, method?: string, timeout?: number, retry?: boolean) {
const actualMethod = method || 'GET';
const actualTimeout = timeout !== undefined ? timeout : 30000;
const shouldRetry = retry !== undefined ? retry : true;
// Implementation details...
}
// With default parameters - much cleaner!
function fetchDataImproved(
endpoint: string,
method: string = 'GET',
timeout: number = 30000,
retry: boolean = true
) {
// Implementation details with no repetitive checks needed
}
This approach works well with TypeScript question mark operators and the nullish coalescing operator, which serve similar purposes but in different contexts.
For Convex developers, applying default parameters follows similar patterns to those described in the Convex documentation, making your backend code more robust and maintainable.
Solving Common Problems with Default Parameters
When working with TypeScript, these are common challenges that default parameters can solve:
Missing Arguments in Function Calls
Default parameters elegantly handle cases where arguments might be missing without requiring verbose fallback logic inside your function:
// Problem: Complex conditional logic for missing arguments
function createReport(title: string, format: string) {
format = format || 'PDF'; // Simple but doesn't handle '' values well
// Implementation...
}
// Solution: Clean default parameter
function createReport(title: string, format: string = 'PDF') {
// Implementation with no conditional fallback needed
}
Maintaining Backward Compatibility
When evolving your codebase, default parameters let you add new options without breaking existing code:
// Adding new parameters while preserving compatibility
function sendNotification(
message: string,
recipients: string[],
priority: string = 'normal',
expiration: number = 86400 // New parameter with a default
) {
// Implementation
}
This pattern is particularly useful when working with TypeScript function types in library code or public APIs.
The Convex custom functions approach uses similar patterns to maintain compatibility while evolving backend APIs.
Final Thoughts about TypeScript Default Parameters
Default parameters are a key feature in TypeScript that simplify your code and improve function flexibility. By providing fallback values, you can create cleaner APIs that handle missing arguments gracefully. Remember to use default parameters thoughtfully - they're perfect for optional configuration but should be avoided for critical values where explicit arguments make more sense. When paired with TypeScript type declarations, default parameters create robust, flexible interfaces that work well in both small projects and large codebases. They're also valuable when working with TypeScript interfaces, allowing you to evolve your APIs without breaking changes.