exactOptionalPropertyTypes
Missing is not the same as undefined
`{ retries?: number }` normally also permits `{ retries: undefined }`. This flag makes the question mark mean only "may be absent".
- Since
- TypeScript 4.4
- strict
- Not in strict
- In your tsconfig
"exactOptionalPropertyTypes": true- Compiled with
"strict": true
The same snippet both times. Only the option changed.
With it off
"exactOptionalPropertyTypes": falsetype Options = { retries?: number } export const options: Options = { retries: undefined }
Compiles clean
With it on
"exactOptionalPropertyTypes": truetype Options = { retries?: number } export const options: Options = { retries: undefined }
Emits TS2375
Why the compiler bothers
The two are different at runtime and the difference is load-bearing: `"retries" in options` is false for one and true for the other, `Object.keys` lists one and not the other, and a merge that spreads defaults will have the explicit `undefined` overwrite the default while the absent key does not. Without this flag the type system cannot tell them apart, so the one API shape where it matters most — an options object with defaults — is exactly the one it cannot describe.
Takeaway
Write `retries?: number | undefined` when you really do accept both.
Where to go next
22 options

