Skip to Content
Course content

23: Optional Properties

Click on the "Edit" button in the top corner of the screen to edit your slide content.

How do I tell TypeScript that a property isn't strictly required?

In the real world, your data is rarely perfect. If you're building a user profile system, every user has a username, but not every user is going to write a bio or link their Twitter account. If you define those as required strings, TypeScript will force you to provide them every single time you create a user object, which is a pain.

To fix this, we use the question mark ? right after the property name in the interface or type alias. This marks the property as "optional."

interface UserProfile {
  username: string;
  bio?: string; // This is optional
  website?: string; // This is also optional
}

const userA: UserProfile = { username: "dev_jane", bio: "Code and Coffee" }; 
const userB: UserProfile = { username: "coding_bob" }; // No bio or website, and TS is happy!

I usually recommend making as few things optional as possible, though. If you make everything optional, you're basically just writing vanilla JavaScript again and losing the safety that makes TypeScript worth using.

Does an optional property just mean it's "undefined"?

Pretty much, yes. Under the hood, when you mark a property as bio?: string, TypeScript actually treats it as string | undefined.

The key difference is what happens during object creation. If you used a union type like bio: string | undefined, you would be forced to explicitly write bio: undefined when creating the object. With the optional ? syntax, you can just leave the key out entirely. It's a quality-of-life improvement that makes your object literals much cleaner.

How do I use these properties without the compiler complaining?

This is where most people hit a wall. Once you've marked a property as optional, TypeScript will stop you from using it directly because it knows the value might be undefined. If you try to call user.bio.toUpperCase(), the compiler will yell at you: "Object is possibly 'undefined'."

You have two main ways to handle this. The old way is a standard if check, but the modern, professional way is using optional chaining (the ?. operator). It tells TypeScript: "Try to access this property; if it's missing, just stop and return undefined instead of crashing the app."

function printBio(user: UserProfile) {
  // This would throw an error if bio is missing:
  // console.log(user.bio.toUpperCase()); 

  // This is safe. If bio is undefined, the whole expression becomes undefined.
  console.log(user.bio?.toUpperCase());
}

When should I use an optional property versus a union type with null?

This is a common architectural debate. In my experience, use ? when the property is truly optional to provide (like an optional setting in a config file). Use string | null when the property must exist, but its value might be intentionally empty or "cleared."

For example, in a database record, a deletedAt timestamp might be null if the record is active. You wouldn't make that optional, because the field exists in the database schema—it just happens to be empty. If you omit the field entirely via ?, you're saying the property might not even exist on the object, which is a different semantic meaning.




📋 Practical Task

Refactoring the Product Catalog Interface

You are working on an e-commerce site. Currently, the Product interface requires every single field, which is causing crashes when adding simple products that don't have a discount or a technical specification list.

Your Task:

  • Modify the Product interface so that discountPrice and specs are optional.
  • Fix the displayProduct function so it doesn't throw a TypeScript error when trying to access the length of the specs array.
interface Product {
  name: string;
  price: number;
  discountPrice: number; // Make this optional
  specs: string[]; // Make this optional
}

function displayProduct(product: Product) {
  console.log(`Product: ${product.name}`);
  // FIX THIS LINE: It currently errors because specs might be undefined
  console.log(`Specifications count: ${product.specs.length}`); 
}

const basicLamp: Product = {
  name: "Desk Lamp",
  price: 25,
  // discountPrice and specs are missing here, which should now be allowed
};

displayProduct(basicLamp);
Rating
0 0

There are no comments for now.

to be the first to leave a comment.