Skip to content

Empty types and types with never as a key behave differently #56691

Open

Description

🔎 Search Terms

Mapped type
unknown

🕗 Version & Regression Information

  • This changed between versions 4.7.4 and 4.8.4

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.0-dev.20231206#code/CYUwxgNghgTiAEYD2A7AzgF3gVwFw5QGsUkB3FAbgCgqMBPABwQEF4BeeAbwG0BpeAJYp4KEADcQMALr4oKOgF8qAemXx1APQD8NVfABySeAFEYMJDCrJ0WKPhTYIEeAB8CoAGZCQwV1wXsONR66vDaumqm5pbWmPAARvaOzm7YKJ7evm6sHNjBaqHhQA

💻 Code

declare const u: unknown;

type A = {[K in never]: any}
//   ^?

// No Error
const a: null | undefined | {} = u;
//    ^?

// Error
const b: null | undefined | A = u;
//    ^?

🙁 Actual behavior

The types a and b appear to be the same, but only the assignment to b causes an error.

🙂 Expected behavior

I'm not sure which is better, I think it's either no error or both errors.

Additional information about the issue

Both were errors in version 4.7.4

Activity

  1. MartinJohns commented on Dec 6, 2023

    @MartinJohns
    Contributor

    What is that mapped type supposed to do?

    Regardless, this seems intentional: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html#improved-intersection-reduction-union-compatibility-and-narrowing

    TypeScript now recognizes this, and allows assignments from unknown to {} | null | undefined.

  2. kazatsuyu commented on Dec 6, 2023

    @kazatsuyu
    Author

    If the possible assignment of unknown to null | undefeind | {} is intentional, then the behavior of a is correct, but b should not be an error.

  3. jcalz commented on Dec 6, 2023

    @jcalz
    Contributor

    I suggest simplifying the example to something like type A = {[K in never]: any} which reproduces the behavior without the added distraction of conditional types.

    Relevant: #49119 and #49119 (comment)

  4. kazatsuyu commented on Dec 6, 2023

    @kazatsuyu
    Author

    Well, it certainly looks like the problem is not that I mapped {}, but that I created a type with never key.

  5. changed the title [-]Empty mapped type and unknown behave strangely[/-] [+]Empty types and types with `never` as a key behave differently[/+] on Dec 6, 2023
  6. RyanCavanaugh commented on Dec 8, 2023

    @RyanCavanaugh
    Member

    I suppose the steelmanned version of the issue looks like this

    export  {}
    declare const u: unknown;
    type Point = { x: number, y: number };
    
    declare function foo<T, K extends keyof T>(obj: T, keys: K[], rest: Omit<T, K> | null | undefined): void;
    const p: Point = { x: 0, y: 0 };
    // Error, but should OK
    foo(p, ["x", "y"], u);
  7. RyanCavanaugh commented on Dec 8, 2023

    @RyanCavanaugh
    Member

    I'm not committing to take a fix for this since it's pretty niche, but if it's straightforward and doesn't break/slow down something else, we can take a PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions