When to use TypeScript's double question mark
The double question mark (??
), or nullish coalescing operator, is a handy feature in TypeScript for handling null and undefined values. It allows you to set a default value for variables that might be null or undefined, making your code more reliable and reducing errors. This is especially useful when working with data from external sources like APIs or user inputs, where missing values are common. By using this operator, your code maintains consistency even when dealing with incomplete data.
What is the Nullish Coalescing Operator?
The nullish coalescing operator (??
) evaluates to its right-hand operand when its left-hand operand is null or undefined; otherwise, it returns the left-hand operand. This makes it perfect for assigning default values without affecting other falsy values like empty strings or zero.
const username = user.name ?? 'Guest';
In this example, username
will be set to user.name
if it exists; otherwise, it will default to 'Guest'.
Using the Double Question Mark in TypeScript
The double question mark is useful in many scenarios, like when dealing with objects that might have missing properties. For instance:
const user = {
name: 'John',
address: null,
};
const username = user.name ?? 'Guest';
const userAddress = user.address ?? 'Unknown';
Here, username
becomes 'John' while userAddress
becomes 'Unknown' because user.address
is null. typescript null coalesce operations like this help prevent errors when working with potentially missing data.
Managing Null and Undefined Values
This operator is valuable when working with objects that may have null properties. It allows you to set default values for these properties, enhancing your code's reliability.
const user = {
name: 'John',
address: null,
};
const username = user.name ?? 'Guest';
const userAddress = user.address ?? 'Unknown';
console.log(username); // John
console.log(userAddress); // Unknown
The code above demonstrates how default value assignment works with the nullish coalescing operator. When integrating with Convex data validation, this pattern helps ensure your application gracefully handles missing data.
Setting Default Values for Function Parameters
You can also use the double question mark to provide default values for function parameters. For example:
function greet(name = 'World' ?? 'Guest') {
console.log(`Hello, ${name}!`);
}
greet(); // Hello, World!
greet(null); // Hello, Guest!
greet('John'); // Hello, John!
There's an important technical detail to note here: In the example above, the nullish coalescing operator (??
) works after the default parameter value is applied. The parameter already defaults to 'World', so the nullish coalescing operator only activates when null
is explicitly passed. This showcases how the double question mark operator can be combined with default parameters for more flexible function definitions.
Preventing Null or Undefined Errors
The double question mark helps prevent errors by ensuring variables have fallback values if they are null or undefined.
const user = {
name: 'John',
address: null,
};
const username = user.name ?? 'Guest';
const userAddress = user.address ?? 'Unknown';
console.log(username.length); // 4
console.log(userAddress.length); // 7
This pattern is essential when working with complex data structures where certain properties might be missing. With proper fallback values in place, your code can safely access properties without throwing errors, even when data is incomplete.
Simplifying Code with Optional Chaining
Combine the double question mark with optional chaining to make your code cleaner. For instance:
const user = {
name: 'John',
address: {
street: '123 Main St',
},
};
const userStreet = user.address?.street ?? 'Unknown';
This example shows how optional chaining works alongside the nullish coalescing operator to safely access nested properties. If either user.address
or user.address.street
is null or undefined, userStreet
will default to 'Unknown'. This technique is especially important when working with external data sources where the structure isn't always guaranteed.
Comparing with the Logical OR Operator
The double question mark and the logical OR operator are different. The OR operator returns the first truthy value, while the double question mark returns the first value unless it's null or undefined.
const message = '' || 'Default message'; // Default message
const message2 = '' ?? 'Default message'; // ''
In the first example, the empty string is falsy, so the OR operator returns 'Default message'. In the second example, the empty string is not null or undefined, so the nullish coalescing operator returns the empty string. This distinction is crucial when processing form inputs where empty strings might represent valid user choices rather than missing data.
Common Challenges and Solutions
Handling Null and Undefined Gracefully
Developers often face challenges with null and undefined values, which can cause errors. The nullish coalescing operator provides a clean solution by ensuring variables have fallback values only when genuinely needed.
// Without nullish coalescing
const count = data.count !== null && data.count !== undefined ? data.count : 0;
// With nullish coalescing
const count = data.count ?? 0;
This approach pairs well with Convex's type system for building robust applications.
Simplifying Conditional Assignments
The nullish coalescing operator makes default value assignments more concise while maintaining the correct behavior for empty strings, zero, and other falsy values:
// The old way
const text = options.text === null || options.text === undefined ? 'Default' : options.text;
// Using nullish coalescing
const text = options.text ?? 'Default';
This technique is valuable when implementing null check logic throughout your codebase.
OR vs. Double Question Mark
Choosing between the double question mark and the logical OR operator depends on your specific requirements:
// Using || (OR)
const userInput = userValue || defaultValue;
// Assigns defaultValue if userValue is ANY falsy value:
// false, 0, '', NaN, null, undefined
// Using ?? (nullish coalescing)
const userInput = userValue ?? defaultValue;
// Assigns defaultValue ONLY if userValue is null or undefined
This distinction becomes especially important when working with forms or API responses. For instance, when implementing validation patterns in TypeScript applications, you'll want to preserve intentionally entered falsy values like empty strings or zeros rather than replacing them with defaults.
// With a form field value:
const count = formData.count ?? 0; // Only uses 0 if count is null/undefined
const message = formData.message ?? 'No message'; // Preserves empty strings
When migrating from JavaScript to TypeScript, be mindful of replacing ||
with ??
where appropriate to maintain expected behavior. The typescript null check is more precise with the nullish coalescing operator than with traditional OR-based fallbacks.
Final Thoughts
TypeScript's double question mark makes handling null and undefined values straightforward. It simplifies your code, reduces potential errors, and improves reliability. Whether in small scripts or large applications, this operator helps provide sensible defaults where needed. The nullish coalescing operator works especially well when combined with type-safe patterns for building robust TypeScript applications.