Optional Properties in TypeScript
Optional properties let you mark object properties as not required. Add a question mark after the property name, and TypeScript knows the value might be undefined. Learn the syntax and safe patterns.
TypeScript optional properties are properties in an object type that do not have to be present. You mark one with a question mark after the property name. When you read an optional property, TypeScript knows the value might be undefined, so it forces you to handle the missing case.
Optional properties are everywhere in real code. Configuration objects, API responses, and user input forms all have fields that may or may not exist. Instead of forcing every property to be required and filling missing ones with placeholders, you mark them as optional and let the compiler guide safe access. See object types in TypeScript for the foundation this builds on.
Marking a property as optional
Add a question mark after the property name in any object type. The syntax works the same on interfaces, type aliases, and inline annotations.
interface PaintOptions {
shape: string;
xPos?: number;
yPos?: number;
}
function paint(opts: PaintOptions) {
console.log(`Painting ${opts.shape}`);
}The shape property is required. But xPos and yPos are optional -- callers can provide none, one, or both. Here are valid calls:
paint({ shape: "circle" });
paint({ shape: "square", xPos: 100 });
paint({ shape: "triangle", xPos: 50, yPos: 75 });All three compile. If you provide xPos or yPos, the value must be a number. The question mark only affects whether the property can be omitted -- it does not change the type when present.
Reading optional properties safely
When you read an optional property under strict null checks, TypeScript widens the type to include undefined. You must narrow it before using it as if it were always present.
function paint(opts: PaintOptions) {
console.log(opts.xPos.toFixed(2));
// Error: 'opts.xPos' is possibly 'undefined'.
}TypeScript is right. If the caller did not provide xPos, calling a method on undefined would crash at runtime. The fix is to check the value first with a conditional. Inside the if block, xPos is narrowed to number, so method calls are safe.
function paint(opts: PaintOptions) {
if (opts.xPos !== undefined) {
console.log(opts.xPos.toFixed(2)); // OK
}
}You can also use optional chaining for single property reads. When xPos is present, this prints the formatted number. When absent, it prints "no position":
function paint(opts: PaintOptions) {
console.log(opts.xPos?.toFixed(2) ?? "no position");
}Providing defaults with destructuring
The cleanest way to handle optional properties is destructuring with default values. This pattern removes undefined from the type entirely inside the function body.
function paint({ shape, xPos = 0, yPos = 0 }: PaintOptions) {
console.log(`Painting ${shape} at (${xPos}, ${yPos})`);
}
paint({ shape: "circle" }); // "Painting circle at (0, 0)"Because xPos and yPos have defaults of 0, they are always number inside the function. The caller can still omit them, but the function body never deals with undefined.
Note that destructuring patterns do not support type annotations on the individual variables. The notation shape: Shape in a destructuring pattern means "rename shape to Shape," not "type shape as Shape." Type the whole parameter object instead, as shown above.
Optional vs required-with-undefined
In most practical code, you want the optional form because it lets callers omit the property. Use the required-plus-undefined form only when you explicitly want to force callers to set the property to something, even if that something is undefined.
| Form | Key can be missing | Value can be undefined |
|---|---|---|
xPos?: number | Yes | Yes |
xPos: number | undefined | No, the key must exist | Yes |
For more on handling potentially missing values, see null and undefined in TypeScript.
The option bag pattern
Optional properties power one of the most common TypeScript patterns: the option bag. Instead of a function with many positional parameters, you accept a single object where every field is optional.
interface FetchOptions {
method?: string;
body?: string;
timeout?: number;
retries?: number;
}The interface declares every option as optional, so callers can pass whichever fields they need and skip the rest. Here is the function that consumes this options object:
function fetchData(url: string, opts: FetchOptions = {}) {
const method = opts.method ?? "GET";
const timeout = opts.timeout ?? 5000;
console.log(`${method} ${url} (timeout: ${timeout}ms)`);
}Inside the function, every option falls back to a sensible default using nullish coalescing. Callers provide only what they need:
fetchData("/api/users");
fetchData("/api/users", { method: "POST" });
fetchData("/api/users", { timeout: 10000, retries: 5 });A typo in a property name is caught immediately because excess property checks reject unknown keys on object literals.
Common mistakes
Using an optional property without checking for undefined. With strict null checks enabled, this is a compile error. Always narrow first or use destructuring defaults.
Assuming an optional property is present because you always pass it. The type must be correct for every call site, not just the ones you remember. If a property is marked optional, the type says it can be absent.
Confusing optional with required-plus-undefined for object creation. The optional form lets callers omit the property. The required-plus-undefined form forces the key to exist. Choose the optional form unless you have a specific reason to force the property key to exist.
Rune AI
Key Insights
- Add a question mark after a property name to mark it as optional in an object type.
- Reading an optional property returns
string | undefined, so check for undefined before use. - Optional properties can be omitted entirely, unlike properties typed with
| undefined. - Destructuring with default values is the cleanest way to handle missing optional properties.
- Optional properties are common in config objects, API responses, and option bags.
Frequently Asked Questions
Can I use optional properties on interfaces and type aliases?
What is the difference between optional and `| undefined`?
How do I provide a default value for an optional property?
Conclusion
Optional properties let you model objects where some fields may or may not be present. Mark a property with a question mark, and TypeScript treats it as potentially undefined. Always check for undefined before using the value, or use destructuring defaults for a cleaner, narrower type inside function bodies.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.