Skip to content

Combination of generic type and mapped types produce unexpected bahaviour #32807

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

Closed
liaokaien opened this issue Aug 11, 2019 · 5 comments
Closed
Labels
Question An issue which isn't directly actionable in code

Comments

@liaokaien
Copy link

I've tried my best to search for related issues and read the document thoroughly but failed to find any useful information. I'm sorry if this bug turns out to be duplicate or even not a bug at all.

TypeScript Version: 3.5.2

Search Terms: conditional types, mapped types, generic

Code

type Concrete = {
  keyOne: string
  keyTwo: string
}

type ConcreteKey = keyof Concrete

type R<T, N extends keyof T> = {
  [P in keyof T]: P extends N ? true : false
};
// R implement without conditional types
type Q<T, N extends keyof T> = {
  [P in N]: true
} & {
  [P in Exclude<keyof T, N>]: false
};
// Function using a concrete type, works as expected
function fn(keys: ConcreteKey[]) {
  let temp: Partial<R<Concrete, ConcreteKey>> = {}
  keys.forEach(key => temp[key] = true)
}
// Function use generic types, report a weird error:
// Type 'true' is not assignable to type 'K extends K ? true : false'.ts(2322)
function fn2<T, K extends keyof T>(keys: K[]) {
  let temp: Partial<R<T, K>> = {}
  keys.forEach(key => temp[key] = true)
}

Expected behavior:
Any property of type R<T,K> could be assigned to true if it extends type K; Therefore true could be assigned to temp[key];

Actual behavior:
Error in function fn2

Type 'true' is not assignable to type 'K extends K ? true : false'.ts(2322)

I suppose type K extends K ? true : false should be automatically resolved to type true.

Playground Link:
Playground Link

I also test the same function with a concrete type and it works as expected. And even if I implement type R without conditional types (Q in example code), the bug still exists, so I guess there is nothing to do with conditional types, but mapped types and generic type;

@jack-williams
Copy link
Collaborator

jack-williams commented Aug 11, 2019

This is working as intended.

I suppose type K extends K ? true : false should be automatically resolved to type true.

The conditional type is distributive so it’s not possible to correctly predict the behaviour until K is instantiated.

Discussion here #31751.

type R<T, N extends keyof T> = {
  [P in keyof T]: [P] extends [N] ? true : false
};

I think this should work.

@liaokaien
Copy link
Author

Thanks for your explanation!

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Aug 16, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.

2 similar comments
@typescript-bot
Copy link
Collaborator

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.

@typescript-bot
Copy link
Collaborator

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants