Skip to content

Fix definitely false check in conditional types #21737

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

Merged
merged 3 commits into from
Feb 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8144,7 +8144,7 @@ namespace ts {
// types with type parameters mapped to the wildcard type, the most permissive instantiations
// possible (the wildcard type is assignable to and from all types). If those are not related,
// then no instatiations will be and we can just return the false branch type.
if (!isTypeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(extendsType))) {
if (!typeMaybeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(extendsType))) {
return instantiateType(baseFalseType, mapper);
}
// The check could be true for some instantiation
Expand Down
20 changes: 20 additions & 0 deletions tests/baselines/reference/conditionalTypes1.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,24 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(157,5): error TS2
type T50 = IsNever<never>; // true
type T51 = IsNever<number>; // false
type T52 = IsNever<any>; // false

// Repros from #21664

type Eq<T, U> = T extends U ? U extends T ? true : false : false;
type T60 = Eq<true, true>; // true
type T61 = Eq<true, false>; // false
type T62 = Eq<false, true>; // false
type T63 = Eq<false, false>; // true

type Eq1<T, U> = Eq<T, U> extends false ? false : true;
type T70 = Eq1<true, true>; // true
type T71 = Eq1<true, false>; // false
type T72 = Eq1<false, true>; // false
type T73 = Eq1<false, false>; // true

type Eq2<T, U> = Eq<T, U> extends true ? true : false;
type T80 = Eq2<true, true>; // true
type T81 = Eq2<true, false>; // false
type T82 = Eq2<false, true>; // false
type T83 = Eq2<false, false>; // true

35 changes: 35 additions & 0 deletions tests/baselines/reference/conditionalTypes1.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,26 @@ type IsNever<T> = T extends never ? true : false;
type T50 = IsNever<never>; // true
type T51 = IsNever<number>; // false
type T52 = IsNever<any>; // false

// Repros from #21664

type Eq<T, U> = T extends U ? U extends T ? true : false : false;
type T60 = Eq<true, true>; // true
type T61 = Eq<true, false>; // false
type T62 = Eq<false, true>; // false
type T63 = Eq<false, false>; // true

type Eq1<T, U> = Eq<T, U> extends false ? false : true;
type T70 = Eq1<true, true>; // true
type T71 = Eq1<true, false>; // false
type T72 = Eq1<false, true>; // false
type T73 = Eq1<false, false>; // true

type Eq2<T, U> = Eq<T, U> extends true ? true : false;
type T80 = Eq2<true, true>; // true
type T81 = Eq2<true, false>; // false
type T82 = Eq2<false, true>; // false
type T83 = Eq2<false, false>; // true


//// [conditionalTypes1.js]
Expand Down Expand Up @@ -415,3 +435,18 @@ declare type IsNever<T> = T extends never ? true : false;
declare type T50 = IsNever<never>;
declare type T51 = IsNever<number>;
declare type T52 = IsNever<any>;
declare type Eq<T, U> = T extends U ? U extends T ? true : false : false;
declare type T60 = Eq<true, true>;
declare type T61 = Eq<true, false>;
declare type T62 = Eq<false, true>;
declare type T63 = Eq<false, false>;
declare type Eq1<T, U> = Eq<T, U> extends false ? false : true;
declare type T70 = Eq1<true, true>;
declare type T71 = Eq1<true, false>;
declare type T72 = Eq1<false, true>;
declare type T73 = Eq1<false, false>;
declare type Eq2<T, U> = Eq<T, U> extends true ? true : false;
declare type T80 = Eq2<true, true>;
declare type T81 = Eq2<true, false>;
declare type T82 = Eq2<false, true>;
declare type T83 = Eq2<false, false>;
75 changes: 75 additions & 0 deletions tests/baselines/reference/conditionalTypes1.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -777,3 +777,78 @@ type T52 = IsNever<any>; // false
>T52 : Symbol(T52, Decl(conditionalTypes1.ts, 203, 27))
>IsNever : Symbol(IsNever, Decl(conditionalTypes1.ts, 198, 47))

// Repros from #21664

type Eq<T, U> = T extends U ? U extends T ? true : false : false;
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))
>T : Symbol(T, Decl(conditionalTypes1.ts, 208, 8))
>U : Symbol(U, Decl(conditionalTypes1.ts, 208, 10))
>T : Symbol(T, Decl(conditionalTypes1.ts, 208, 8))
>U : Symbol(U, Decl(conditionalTypes1.ts, 208, 10))
>U : Symbol(U, Decl(conditionalTypes1.ts, 208, 10))
>T : Symbol(T, Decl(conditionalTypes1.ts, 208, 8))

type T60 = Eq<true, true>; // true
>T60 : Symbol(T60, Decl(conditionalTypes1.ts, 208, 65))
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))

type T61 = Eq<true, false>; // false
>T61 : Symbol(T61, Decl(conditionalTypes1.ts, 209, 26))
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))

type T62 = Eq<false, true>; // false
>T62 : Symbol(T62, Decl(conditionalTypes1.ts, 210, 27))
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))

type T63 = Eq<false, false>; // true
>T63 : Symbol(T63, Decl(conditionalTypes1.ts, 211, 27))
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))

type Eq1<T, U> = Eq<T, U> extends false ? false : true;
>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28))
>T : Symbol(T, Decl(conditionalTypes1.ts, 214, 9))
>U : Symbol(U, Decl(conditionalTypes1.ts, 214, 11))
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))
>T : Symbol(T, Decl(conditionalTypes1.ts, 214, 9))
>U : Symbol(U, Decl(conditionalTypes1.ts, 214, 11))

type T70 = Eq1<true, true>; // true
>T70 : Symbol(T70, Decl(conditionalTypes1.ts, 214, 55))
>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28))

type T71 = Eq1<true, false>; // false
>T71 : Symbol(T71, Decl(conditionalTypes1.ts, 215, 27))
>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28))

type T72 = Eq1<false, true>; // false
>T72 : Symbol(T72, Decl(conditionalTypes1.ts, 216, 28))
>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28))

type T73 = Eq1<false, false>; // true
>T73 : Symbol(T73, Decl(conditionalTypes1.ts, 217, 28))
>Eq1 : Symbol(Eq1, Decl(conditionalTypes1.ts, 212, 28))

type Eq2<T, U> = Eq<T, U> extends true ? true : false;
>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29))
>T : Symbol(T, Decl(conditionalTypes1.ts, 220, 9))
>U : Symbol(U, Decl(conditionalTypes1.ts, 220, 11))
>Eq : Symbol(Eq, Decl(conditionalTypes1.ts, 204, 24))
>T : Symbol(T, Decl(conditionalTypes1.ts, 220, 9))
>U : Symbol(U, Decl(conditionalTypes1.ts, 220, 11))

type T80 = Eq2<true, true>; // true
>T80 : Symbol(T80, Decl(conditionalTypes1.ts, 220, 54))
>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29))

type T81 = Eq2<true, false>; // false
>T81 : Symbol(T81, Decl(conditionalTypes1.ts, 221, 27))
>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29))

type T82 = Eq2<false, true>; // false
>T82 : Symbol(T82, Decl(conditionalTypes1.ts, 222, 28))
>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29))

type T83 = Eq2<false, false>; // true
>T83 : Symbol(T83, Decl(conditionalTypes1.ts, 223, 28))
>Eq2 : Symbol(Eq2, Decl(conditionalTypes1.ts, 218, 29))

108 changes: 108 additions & 0 deletions tests/baselines/reference/conditionalTypes1.types
Original file line number Diff line number Diff line change
Expand Up @@ -883,3 +883,111 @@ type T52 = IsNever<any>; // false
>T52 : false
>IsNever : IsNever<T>

// Repros from #21664

type Eq<T, U> = T extends U ? U extends T ? true : false : false;
>Eq : Eq<T, U>
>T : T
>U : U
>T : T
>U : U
>U : U
>T : T
>true : true
>false : false
>false : false

type T60 = Eq<true, true>; // true
>T60 : true
>Eq : Eq<T, U>
>true : true
>true : true

type T61 = Eq<true, false>; // false
>T61 : false
>Eq : Eq<T, U>
>true : true
>false : false

type T62 = Eq<false, true>; // false
>T62 : false
>Eq : Eq<T, U>
>false : false
>true : true

type T63 = Eq<false, false>; // true
>T63 : true
>Eq : Eq<T, U>
>false : false
>false : false

type Eq1<T, U> = Eq<T, U> extends false ? false : true;
>Eq1 : Eq1<T, U>
>T : T
>U : U
>Eq : Eq<T, U>
>T : T
>U : U
>false : false
>false : false
>true : true

type T70 = Eq1<true, true>; // true
>T70 : true
>Eq1 : Eq1<T, U>
>true : true
>true : true

type T71 = Eq1<true, false>; // false
>T71 : false
>Eq1 : Eq1<T, U>
>true : true
>false : false

type T72 = Eq1<false, true>; // false
>T72 : false
>Eq1 : Eq1<T, U>
>false : false
>true : true

type T73 = Eq1<false, false>; // true
>T73 : true
>Eq1 : Eq1<T, U>
>false : false
>false : false

type Eq2<T, U> = Eq<T, U> extends true ? true : false;
>Eq2 : Eq2<T, U>
>T : T
>U : U
>Eq : Eq<T, U>
>T : T
>U : U
>true : true
>true : true
>false : false

type T80 = Eq2<true, true>; // true
>T80 : true
>Eq2 : Eq2<T, U>
>true : true
>true : true

type T81 = Eq2<true, false>; // false
>T81 : false
>Eq2 : Eq2<T, U>
>true : true
>false : false

type T82 = Eq2<false, true>; // false
>T82 : false
>Eq2 : Eq2<T, U>
>false : false
>true : true

type T83 = Eq2<false, false>; // true
>T83 : true
>Eq2 : Eq2<T, U>
>false : false
>false : false

20 changes: 20 additions & 0 deletions tests/cases/conformance/types/conditional/conditionalTypes1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,23 @@ type IsNever<T> = T extends never ? true : false;
type T50 = IsNever<never>; // true
type T51 = IsNever<number>; // false
type T52 = IsNever<any>; // false

// Repros from #21664

type Eq<T, U> = T extends U ? U extends T ? true : false : false;
type T60 = Eq<true, true>; // true
type T61 = Eq<true, false>; // false
type T62 = Eq<false, true>; // false
type T63 = Eq<false, false>; // true

type Eq1<T, U> = Eq<T, U> extends false ? false : true;
type T70 = Eq1<true, true>; // true
type T71 = Eq1<true, false>; // false
type T72 = Eq1<false, true>; // false
type T73 = Eq1<false, false>; // true

type Eq2<T, U> = Eq<T, U> extends true ? true : false;
type T80 = Eq2<true, true>; // true
type T81 = Eq2<true, false>; // false
type T82 = Eq2<false, true>; // false
type T83 = Eq2<false, false>; // true