Skip to content

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

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
kazatsuyu opened this issue Dec 6, 2023 · 6 comments Β· May be fixed by #56974
Open

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

kazatsuyu opened this issue Dec 6, 2023 · 6 comments Β· May be fixed by #56974
Labels
Bug A bug in TypeScript Help Wanted You can do this
Milestone

Comments

@kazatsuyu
Copy link

kazatsuyu commented Dec 6, 2023

πŸ”Ž 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

@MartinJohns
Copy link
Contributor

MartinJohns commented Dec 6, 2023

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.

@kazatsuyu
Copy link
Author

kazatsuyu commented Dec 6, 2023

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.

@jcalz
Copy link
Contributor

jcalz commented Dec 6, 2023

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)

@kazatsuyu
Copy link
Author

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

@kazatsuyu kazatsuyu changed the title Empty mapped type and unknown behave strangely Empty types and types with never as a key behave differently Dec 6, 2023
@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Dec 8, 2023

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);

@RyanCavanaugh
Copy link
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

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this labels Dec 8, 2023
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Dec 8, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Bug A bug in TypeScript Help Wanted You can do this
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants