C.W.K.
Stream
Lesson 05 of 05 · published

`exactOptionalPropertyTypes`

~7 min · strict-mode, exact-optional-property-types, optional

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"{ a?: string } means 'a may be missing.' It doesn't mean 'a may be explicitly undefined.' The flag enforces the difference."

What it changes

Without the flag: { a?: string } accepts both {} and { a: undefined }. They're treated as equivalent. With the flag: only the first is accepted; { a: undefined } is now a type error unless you write the type as { a?: string | undefined }.

The difference matters in two real-world scenarios: serialization (JSON.stringify drops undefined keys, but missing keys and undefined keys round-trip differently) and property merging (Object.assign treats {a: undefined} as 'set a to undefined,' not 'leave a alone').

The migration cost

Most codebases have lots of places where {a: undefined} was used to mean 'no value here.' Turning on this flag exposes them all. The fix is usually either:

  • Stop setting the property: omit it entirely.
  • Make the type allow explicit undefined: { a?: string | undefined }.
  • Stop conflating missing with undefined in the rest of the code.
The flag is pedantic in the best way: it forces you to clarify whether 'absent' and 'present-but-undefined' are the same. Most of the time they should be the same — and the flag's check confirms it. The cases where they differ are exactly the bugs the flag is helping you find.

Code

Without and with exactOptionalPropertyTypes·typescript
interface Config {
  host?: string;
}

// Without exactOptionalPropertyTypes:
const a: Config = {};                     // ✅
const b: Config = { host: undefined };     // ✅ also accepted

// With the flag:
const c: Config = {};                     // ✅
const d: Config = { host: undefined };     // ❌ — host must be omitted or be a string

// To allow both, declare it explicitly:
interface Config2 {
  host?: string | undefined;
}
const e: Config2 = { host: undefined };    // ✅

External links

Exercise

Take a small codebase. Turn on exactOptionalPropertyTypes. Count the errors. For each, decide whether to omit the property or to extend the type to allow explicit undefined. Notice which case is more common — and what that tells you about the codebase's habits.
Hint
Most projects have a mix: explicit undefined was historically used to mean 'no value,' but omission is the cleaner choice. The flag's value is the forced inventory.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.