Description
TypeScript Version: 3.6.3
Search Terms: spread optional undefined object properties property
Code
Here's an example of spreading an object with optional properties:
const myQueryDefaults: { a: number; } = { a: 1 };
const myQuery: { a?: number; } = {};
const result = { ...myQueryDefaults, ...myQuery };
// type is `number`
// runtime value is `number`
result.a;
The above example makes sense. However, an optional property does not only mean "this property may not exist" ({}
)—it also means "this property may exist with a value of undefined
" ({ a: undefined }
). (Related: #13195.)
As a result of this, the type information may mismatch the actual types at runtime:
const myQueryDefaults: { a: number; } = { a: 1 };
const myQuery: { a?: number; } = { a: undefined };
const result = { ...myQueryDefaults, ...myQuery };
// type is `number`, but runtime value is `undefined`!!
// expected type: `number | undefined`
result.a;
… which could result in runtime exceptions:
result.a.toString(); // runtime exception, because `result.a` is `undefined`
Ideally optional properties would only mean "this property may not exist" (#13195), in which case the existing behaviour with spreading makes sense. However, in the interim, perhaps the behaviour of spreading should be changed?
Extracted from #13195 (comment)
Also potentially related: #31025