Some fields are genuinely optional. note?: string means a note can be absent. Reading it gives string or undefined, so calling a string method immediately is unsafe. A required field with an empty string is a different model: the field exists, but contains no text.
Use a fallback when absence has an obvious display meaning. JavaScript’s nullish coalescing operator ?? selects the right-hand value only when the left is null or undefined. It preserves 0, false, and empty strings. Unlike ||, it does not treat every falsy value as missing.
This course enables exactOptionalPropertyTypes. An optional string property may be omitted, but assigning an explicit undefined is not the same contract. For now, omit absent fields instead of creating them with undefined. Day 3 will introduce the union syntax for deliberately allowing multiple types; you do not need it to finish today’s exercises.
An interface is another way to name an object shape: interface Session { topic: string; minutes: number }. Both an interface and a type alias can describe these records. We use type aliases consistently in the remaining beginner lessons, especially when introducing unions. For the flat records here, either spelling works. Use type aliases for the rest of this course; more interface features can wait.
Avoid turning required fields into optional ones just to silence an error. Ask whether the rest of the program can do its job without the value. A missing topic probably requires rejection; an absent note can safely display a fallback.
Predict, check, then run
Before running, write down the output and explain which information the checker knows. Click Check types first, then Check & run.
interface Session {
topic: string;
note?: string;
}
function describe(session: Session): string {
return `${session.topic}: ${session.note ?? "No note"}`;
}
console.log(describe({ topic: "Objects" }));
console.log(describe({ topic: "Types", note: "" }));Enable JavaScript to edit and type-check this example.
Check your prediction
Objects: No note
Types: Read a real compiler error
This editor distinguishes an omitted property from one explicitly set to undefined. Read the suggested type change, then decide whether the data really needs it.
type Session = {
topic: string;
note?: string;
};
const session: Session = { topic: "Types", note: undefined };
console.log(session.note);Enable JavaScript to edit and type-check this example.
Check your diagnosis
For an absent note, remove the note property. If the contract intentionally permits an explicit undefined, declare note?: string | undefined. The vertical bar describes alternatives; Day 3 explains unions in detail.
Absence and empty text require different policies
An optional field can be absent. When read, its value may therefore be undefined. A present empty string is different data. Decide whether empty text means a deliberate blank or should be treated as missing before choosing a fallback expression.
With this course’s exact optional-property checking, omitting a field is different from explicitly assigning undefined to a field whose declared value type is string. You can read a missing field as undefined without making every explicit undefined assignment valid.
interface Book {
title: string;
note?: string;
}
function label(book: Book): string {
return book.note ?? "No note";
}
console.log(label({ title: "Types" }));
console.log(label({ title: "Types", note: "" }) === "");Enable JavaScript to edit and type-check this example.
Check your prediction
No note
true The fallback handles absence and preserves deliberately empty text. Replacing ?? with || would merge these two cases, which might or might not match the intended interface policy.
interface Book {
title: string;
note?: string;
}
const omitted: Book = { title: "Types" };
const present: Book = { title: "Types", note: "Review" };
console.log("note" in omitted);
console.log("note" in present);
console.log(omitted.note === undefined);Enable JavaScript to edit and type-check this example.
Check your prediction
false
true
true Presence is a property-level question. A read can return undefined when the field is absent; that does not mean the object contains an explicitly assigned note property.
Try the rule on new inputs
Test omitted, empty and nonempty notes. Then try the intentional assignment note:undefined and inspect the compiler rule before restoring it. State whether your formatter preserves a deliberate empty note.
Your turn
Optional Properties & Interfaces: practise
Define a Course record with title:string and optional subtitle:string. Write caption returning the subtitle when present, otherwise “Introduction”. An empty subtitle must stay empty. Print Introduction and then Advanced practice for two examples.
// Define Course and caption. Test both an absent and a present subtitle.Enable JavaScript to edit and type-check this example.
Hint 1: the idea
The fallback should apply to absence rather than every falsy value.
Hint 2: a first step
Read course.subtitle and combine it with a nullish fallback.
Show one solution
type Course = {
title: string;
subtitle?: string;
};
function caption(course: Course): string {
return course.subtitle ?? "Introduction";
}
console.log(caption({ title: "Types" }));
console.log(caption({ title: "Types", subtitle: "Advanced practice" }));Enable JavaScript to edit and type-check this example.
Introduction
Advanced practiceExplain the types at the function boundary and the runtime checks, if any. Compare your approach before copying this answer.
Change it and explain it
Test subtitle="" and explain why it differs from a missing subtitle. Replace the alias with an equivalent interface without changing behavior. Finally try assigning subtitle:undefined and explain this course’s exact optional-property rule.
Completion is saved in this browser only. It does not measure mastery.