Skip to content

Instantly share code, notes, and snippets.

@qntm
Last active September 22, 2025 15:06
Show Gist options
  • Save qntm/00ce3b74c3331e0032453162610df1d1 to your computer and use it in GitHub Desktop.
Save qntm/00ce3b74c3331e0032453162610df1d1 to your computer and use it in GitHub Desktop.
TypeScript: key-optional vs. value-optional

TypeScript: key-optional vs. value-optional

Normal object type with a required property

type Apple = { numPips: number }

const apple1: Apple = {}                     // ❌ type error
const apple2: Apple = { numPips: undefined } // ❌ type error
const apple3: Apple = { numPips: 3 }         // ✅ valid

Value-optional

type Apple = { numPips: number | undefined }

const apple1: Apple = {}                     // ❌ type error
const apple2: Apple = { numPips: undefined } // ✅ valid
const apple3: Apple = { numPips: 3 }         // ✅ valid

This type forces the consumer to always consider and explicitly specify numPips, even if it is undefined.

Key-optional

type Apple = { numPips?: number }

const apple1: Apple = {}                     // ✅ valid
const apple2: Apple = { numPips: undefined } // ❌ type error
const apple3: Apple = { numPips: 3 }         // ✅ valid

Note that JSON.parse(JSON.stringify(apple2)) yields {}, equivalent to apple1 - in other words, information would be lost if apple2 were considered valid. Using a key-optional type protects us from this, and means we can use the same type on both sides of the JSON interface.

Key- and value-optional

type Apple = { numPips?: number | undefined }

const apple1: Apple = {}                     // ✅ valid
const apple2: Apple = { numPips: undefined } // ✅ valid
const apple3: Apple = { numPips: 3 }         // ✅ valid

In my view this type is unnecessarily permissive.

@qntm
Copy link
Author

qntm commented Sep 22, 2025

Would consider swapping in a better example than apples with pips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment