Skip to content

Partial<T>[K] is not assignable to T[K] | undefined #47523

Closed
@hearnden

Description

@hearnden

Bug Report

...ok, I lied a little:

  • it is assignable if T is a type variable / generic; but
  • it is not assignable if T is concrete.

So this report can be seen either as the lack of support of an expected rule (when T is concrete), or an inconsistency between the rules for generics and the rules for concretes.

🔎 Search Terms

Searching for:

  • "Partial"
  • "Partial undefined"

I found these potentially related issues:

#45257 looks very similar. However, I think this report is a simpler case, and seems more directly related to the definition of Partial<> / optional properties (?), as something that adds | undefined to the type of a property access expression. It also looks to me like a fix for this report would fix #45257 naturally.

#31675 also looks related, but from the non-nullable perspective rather than the nullable one. The non-nullable inference rule also appears to be missing from both generic inference and concrete inference (e.g., NonNullable<Partial<T>[K]> is not assignable for T[K] for both generic T and concrete T), so at least there isn't an inconsistency there.

🕗 Version & Regression Information

This changed between versions 3.3.3 and 3.5.1.
In 3.3.3, Partial<T>[K] was assignable to T[K] | undefined for both generic T and concrete T.
From 3.5.1, assignability is still allowed for generic T, but not for any particular concrete T.

⏯ Playground Link

Playground link with relevant code

💻 Code

type Foo = {
    x: number,
    y: string,
};

/** Reads a key of any Partial<T> as an optional. */
function getValueGeneric<T, K extends keyof T>(o: Partial<T>, k: K): T[K] | undefined {
    return o[k];  // Ok: Type 'Partial<T>[K]' is assignable to type 'T[K] | undefined'
}

/** Reads a key of a Partial<Foo> as an optional. */
function getValueConcrete<K extends keyof Foo>(o: Partial<Foo>, k: K): Foo[K] | undefined {
    return o[k];  // Error: Type 'Partial<Foo>[K]' is not assignable to type 'Foo[K] | undefined'
}

🙁 Actual behavior

  • Partial<T>[K] is assignable to T[K] | undefined when T is a generic
  • Partial<T>[K] is not assignable to T[K] | undefined when T is concrete

🙂 Expected behavior

  • Assignability of Partial<T>[K] to T[K] | undefined should be consistent for both generic T and concrete T
  • Both should be allowed

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureFix AvailableA PR has been opened for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions