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

Conditional types bug with scenario involving mapped types #25171

Closed
MastroLindus opened this issue Jun 23, 2018 · 2 comments
Closed

Conditional types bug with scenario involving mapped types #25171

MastroLindus opened this issue Jun 23, 2018 · 2 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@MastroLindus
Copy link

TypeScript Version: 2.9.2

Found two bugs while creating some conditional types using mapped types
Scenario 1

Code
Scenario 1

type Obj = {
  a: string;
  b: number;
};

type Obj2 = {
  c: boolean;
  d: number;
}


type Keys = keyof Obj | keyof Obj2;

function func<T extends Keys>(p: T extends keyof Obj ? Obj[T] : Obj2[T]);

Expected behavior:
function declaration is allowed
Actual behavior:
function declaration errors, saying that T cannot be used to index Obj2, even if it should be allowed.
There's a workaround for this by declaring the function like this:
function func<T extends Keys>(p: T extends keyof Obj ? Obj[T] : T extends keyof Obj2 ? Obj2[T] : never);

However this workaround causes the bug of scenario 2.

Scenario 2

Code

type TestType = "a" | "b";
type Obj = {
  a: string;
  b: number;
};

function func<T extends TestType>(value: T extends TestType ? Obj[T]: never) { };

function func2<T extends TestType>(value: T extends "a" ? string : number) { };



interface Prop1 {
  update<T extends TestType>(value: T extends "a" ? string : number) : void;
}

const x: Prop1 = { update: func }; //doesn't work
const y: Prop1 = { update: func2 }; //works


Actual behavior:
the line were x is declared is giving an error that func is not assignable to the update function of Prop1, even if it should.

Expected behavior:
x should be allowed to be defined.

I know that the type of func is a bit stupid (the conditional type is not necessary here), but in my use case a similar type comes from the problem in scenario 1, forcing me to type it that way.
The problem is in the ": never" part of the conditional type, as another conditional type that doesn't have that :never part seems to work.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 25, 2018

Generic types do not behave any differently if they are constrained to unit types. in general the compiler can not make assumptions about the generic type possible values being limited to one set or another in the presence of intersection types.

For the first example, func can be declared as:

declare function func<T extends Keys>(p: (Obj & Obj2)[T]): void;

For the second example, comparing conditional types really assumes they have to be identical. We are looking into updating some of these relationships, but so far we can not conclusively prove or disprove additional higher order relationships, see #24940 for related discussions.

@mhegazy mhegazy added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jun 25, 2018
@MastroLindus
Copy link
Author

Thank you for your answer. I understand that both scenarios are quite complicated and I expected it to be a current design limitation, but you guys have been made so many great advancements in what the compiler can actually do that I hope that sooner or later something similar will be possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

2 participants