Skip to content

Feature request: strictPartial mode #21159

Closed
@Jessidhia

Description

@Jessidhia

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.

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/d0fdb378/types/react/index.d.ts#L283-L289

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions