Description
This is a request to have a mode that has stricter optional object keys, such as the ones generated by the Partial
mapped type. The idea is to allow reading a possibly-missing key, where its type will include |undefined
, but not writing.
This is important for use cases that involve Object.assign
or object spreads. Having a key assigned to undefined
will overwrite an existing key by putting the value undefined
, which currently allows you to break type correctness.
Code
interface Foo {
bar: string
}
const foo1: Foo = { bar: '' } // ok
const foo2: Partial<Foo> = {} // ok
const foo3: Partial<Foo> = { bar: '' } // ok
const foo4: Partial<Foo> = { bar: undefined } // type error under --strictPartial
function test (foo: Foo, partial: Partial<Foo>) {
const bar1 = foo.bar // typeof bar1 == string
const bar2 = partial.bar // typeof bar2 == string|undefined
}
test(foo1, foo1)
test(foo1, foo2)
test(foo1, foo3)
// if some fancy type tracking is done on foo3, otherwise type error
test(foo3, foo3)
Example of current code that breaks because there is no strictPartial:
interface Foo {
bar: string
}
const foo: Foo = { bar: '' }
const partial: Partial<Foo> = { bar: undefined } // would be an error under --strictPartial
const merged: Foo = { ...foo, ...partial } // accepted
const { bar } = merged // typeof bar is string
// bar is actually `undefined`!
The type definitions for React currently works around it by using generics, keyof
and Pick
, but this hack can only be used for function arguments, and the function must be converted into a generic function.
If a type actually means to accept undefined
itself as a valid value, then its declaration should include |undefined
. An additional standard mapped type (name 🚲🏠) can be used to not only make keys optional but also |undefined
them, and those would be appropriate for use cases such as inputs to object destructuring with defaults.