Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Two same types (mapped type of generic param) are not assignable to each other #49653

Open
csr632 opened this issue Jun 23, 2022 · 3 comments
Open
Assignees
Labels
Needs Investigation This issue needs a team member to investigate its status.

Comments

@csr632
Copy link

csr632 commented Jun 23, 2022

Bug Report

🔎 Search Terms

Keywords: generic function, mapped types

Errors:

  1. Type 'T1' is not assignable to type 'T2'.
  2. Two different types with this name exist, but they are unrelated.

I got both error messages in my original code, but only the first error message is left in the minimal reproduce.

🕗 Version & Regression Information

4.7.2

All other versions also have this issue.

⏯ Playground Link

https://www.typescriptlang.org/play?#code/C4TwDgpgBAYgjFAvFAPAFQHwAoCGAnAcwC4o0BKJDKAJTnQwG4AoUSGuzJKAbyaigDaAaSgBLAHZQA1hBAB7AGakoOAM5QA5MAirgGqBAAe28QBN1IgPxRxEAG4Q8UEkIC6JAAzMAvsyYB6fwNDHABjYAAbEChgAAtoVRwAW2hWCBZwaBgAJi56XEISckoabPpmNNL6Ll5+YTFJGXklNBV1LR09YJNzKCsbe0dnPvcoLyZfJiZTCFCI-GgIiGAoOzgSeGYZuYWoJZW7bI3svzWuQ4YoQKgAUTw8OTwmQ-O4S+u7h6emIA

💻 Code

type F1 = <T>(arg: T) => R1<T>;
type R1<T> = {
  [K in keyof T as 'test' extends K ? never : K]: 0;
};

// exactly the same type
type F2 = <T>(arg: T) => R2<T>;
type R2<T> = {
  [K in keyof T as 'test' extends K ? never : K]: 0;
};

declare let v1: F1;
declare let v2: F2;

v1 = v2; // Error
v2 = v1; // Error

The problem appears when a conditional type is used in a key remapping of mapped types.

🙁 Actual behavior

The two same types are not assignable to each other.

🙂 Expected behavior

The two same types should be assignable to each other. Because they are written in the same way.

In my case, the two "same-written type declarations" exist because they come from the same package with two different versions.

@csr632
Copy link
Author

csr632 commented Jun 23, 2022

Maybe related to #48626 (comment)? I don't fully understand the comment.

@csr632 csr632 changed the title Two same types (generic function) is not assignable to each other Two same types (generic function) are not assignable to each other Jun 23, 2022
@csr632 csr632 changed the title Two same types (generic function) are not assignable to each other Two same types (mapped type of generic param) are not assignable to each other Jun 23, 2022
@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Jun 30, 2022
@ahejlsberg
Copy link
Member

The issue here is that we only consider two mapped types with as clauses related if the as clause types are identical. We could probably be a bit more flexible here. Meanwhile, the workaround is to use a shared as type:

type N<K> = 'test' extends K ? never : K;

type F1 = <T>(arg: T) => R1<T>;
type R1<T> = {
  [K in keyof T as N<K>]: 0;
};

type F2 = <T>(arg: T) => R2<T>;
type R2<T> = {
  [K in keyof T as N<K>]: 0;
};

@ehmicky
Copy link

ehmicky commented Nov 3, 2022

I am running into the same issue and found a slightly simpler example. Link to playground.

type R1 = <T extends PropertyKey>() => {
  [K in T as K extends unknown ? K : K]: 0
}

type R2 = <T extends PropertyKey>() => {
  [K in T as K extends unknown ? K : K]: 0
}

declare let v1: R1;
declare let v2: R2;

v1 = v2; // Error
v2 = v1; // Error
Type 'R2' is not assignable to type 'R1'.
  Type '{ [K in T as K extends unknown ? K : K]: 0; }' is not assignable to type '{ [K in T as K extends unknown ? K : K]: 0; }'. 
  Two different types with this name exist, but they are unrelated.

Removing as K extends unknown ? K : K (even though this clause is a noop) unexpectedly removes that error.

Unfortunately, in my case, the workaround described by @ahejlsberg is not possible because R1 and R2 are actually two instances of the same package installed in different places in node_modules. This leads to my package's types not being assignable with themselves (or more precisely, a copy of themselves).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests

4 participants