type Apple = { numPips: number }
const apple1: Apple = {} // ❌ type error
const apple2: Apple = { numPips: undefined } // ❌ type error
const apple3: Apple = { numPips: 3 } // ✅ validtype Apple = { numPips: number | undefined }
const apple1: Apple = {} // ❌ type error
const apple2: Apple = { numPips: undefined } // ✅ valid
const apple3: Apple = { numPips: 3 } // ✅ validThis type forces the consumer to always consider and explicitly specify numPips, even if it is undefined.
type Apple = { numPips?: number }
const apple1: Apple = {} // ✅ valid
const apple2: Apple = { numPips: undefined } // ❌ type error
const apple3: Apple = { numPips: 3 } // ✅ validNote 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.
type Apple = { numPips?: number | undefined }
const apple1: Apple = {} // ✅ valid
const apple2: Apple = { numPips: undefined } // ✅ valid
const apple3: Apple = { numPips: 3 } // ✅ validIn my view this type is unnecessarily permissive.
Would consider swapping in a better example than apples with pips.