Skip to content

Commit 0d93eb9

Browse files
authored
Merge pull request #30133 from Microsoft/revert-conditional-type-invariance
Revert "Merge pull request #27697 from mattmccutchen/issue-27118"
2 parents 4718ff8 + f77b43c commit 0d93eb9

File tree

6 files changed

+701
-607
lines changed

6 files changed

+701
-607
lines changed

src/compiler/checker.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -12724,11 +12724,10 @@ namespace ts {
1272412724
else if (source.flags & TypeFlags.Conditional) {
1272512725
if (target.flags & TypeFlags.Conditional) {
1272612726
// Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if
12727-
// they have the same distributivity, T1 and T2 are identical types, U1 and U2 are identical
12728-
// types, X1 is related to X2, and Y1 is related to Y2.
12729-
if ((<ConditionalType>source).root.isDistributive === (<ConditionalType>target).root.isDistributive &&
12730-
isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
12731-
isTypeIdenticalTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType)) {
12727+
// one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2,
12728+
// and Y1 is related to Y2.
12729+
if (isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
12730+
(isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) || isRelatedTo((<ConditionalType>target).checkType, (<ConditionalType>source).checkType))) {
1273212731
if (result = isRelatedTo(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target), reportErrors)) {
1273312732
result &= isRelatedTo(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target), reportErrors);
1273412733
}

tests/baselines/reference/conditionalTypes2.errors.txt

+71-65
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
1-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(16,5): error TS2322: Type 'Covariant<B>' is not assignable to type 'Covariant<A>'.
2-
Types of property 'foo' are incompatible.
3-
Type 'B extends string ? B : number' is not assignable to type 'A extends string ? A : number'.
4-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(17,5): error TS2322: Type 'Covariant<A>' is not assignable to type 'Covariant<B>'.
5-
Types of property 'foo' are incompatible.
6-
Type 'A extends string ? A : number' is not assignable to type 'B extends string ? B : number'.
7-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(21,5): error TS2322: Type 'Contravariant<B>' is not assignable to type 'Contravariant<A>'.
8-
Types of property 'foo' are incompatible.
9-
Type 'B extends string ? keyof B : number' is not assignable to type 'A extends string ? keyof A : number'.
10-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(22,5): error TS2322: Type 'Contravariant<A>' is not assignable to type 'Contravariant<B>'.
11-
Types of property 'foo' are incompatible.
12-
Type 'A extends string ? keyof A : number' is not assignable to type 'B extends string ? keyof B : number'.
13-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(26,5): error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
1+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(15,5): error TS2322: Type 'Covariant<A>' is not assignable to type 'Covariant<B>'.
2+
Type 'A' is not assignable to type 'B'.
3+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(19,5): error TS2322: Type 'Contravariant<B>' is not assignable to type 'Contravariant<A>'.
4+
Type 'A' is not assignable to type 'B'.
5+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(24,5): error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
146
Types of property 'foo' are incompatible.
157
Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'.
16-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(27,5): error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
8+
Type 'keyof B' is not assignable to type 'keyof A'.
9+
Type 'string | number | symbol' is not assignable to type 'keyof A'.
10+
Type 'string' is not assignable to type 'keyof A'.
11+
Type 'string' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
12+
Type 'keyof B' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
13+
Type 'string | number | symbol' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
14+
Type 'string' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
15+
Type 'keyof B' is not assignable to type '"valueOf"'.
16+
Type 'string | number | symbol' is not assignable to type '"valueOf"'.
17+
Type 'string' is not assignable to type '"valueOf"'.
18+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,5): error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
1719
Types of property 'foo' are incompatible.
1820
Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'.
19-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract<Extract<T, Foo>, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
21+
Type 'A' is not assignable to type 'B'.
22+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(73,12): error TS2345: Argument of type 'Extract<Extract<T, Foo>, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
2023
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
2124
Type 'Extract<Foo & T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
2225
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
23-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(76,12): error TS2345: Argument of type 'Extract<T, Foo & Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
26+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(74,12): error TS2345: Argument of type 'Extract<T, Foo & Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
2427
Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
25-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(77,12): error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
28+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
2629
Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
2730
Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
28-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(165,5): error TS2322: Type 'MyElement<A>' is not assignable to type 'MyElement<B>'.
29-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(170,5): error TS2322: Type 'MyAcceptor<B>' is not assignable to type 'MyAcceptor<A>'.
30-
tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2322: Type 'Dist<T>' is not assignable to type 'Aux<{ a: T; }>'.
3131

3232

33-
==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (12 errors) ====
34-
// #27118: Conditional types are now invariant in the check type.
35-
33+
==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (7 errors) ====
3634
interface Covariant<T> {
3735
foo: T extends string ? T : number;
3836
}
@@ -46,29 +44,19 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
4644
}
4745

4846
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
49-
a = b; // Error
50-
~
51-
!!! error TS2322: Type 'Covariant<B>' is not assignable to type 'Covariant<A>'.
52-
!!! error TS2322: Types of property 'foo' are incompatible.
53-
!!! error TS2322: Type 'B extends string ? B : number' is not assignable to type 'A extends string ? A : number'.
47+
a = b;
5448
b = a; // Error
5549
~
5650
!!! error TS2322: Type 'Covariant<A>' is not assignable to type 'Covariant<B>'.
57-
!!! error TS2322: Types of property 'foo' are incompatible.
58-
!!! error TS2322: Type 'A extends string ? A : number' is not assignable to type 'B extends string ? B : number'.
51+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
5952
}
6053

6154
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
6255
a = b; // Error
6356
~
6457
!!! error TS2322: Type 'Contravariant<B>' is not assignable to type 'Contravariant<A>'.
65-
!!! error TS2322: Types of property 'foo' are incompatible.
66-
!!! error TS2322: Type 'B extends string ? keyof B : number' is not assignable to type 'A extends string ? keyof A : number'.
67-
b = a; // Error
68-
~
69-
!!! error TS2322: Type 'Contravariant<A>' is not assignable to type 'Contravariant<B>'.
70-
!!! error TS2322: Types of property 'foo' are incompatible.
71-
!!! error TS2322: Type 'A extends string ? keyof A : number' is not assignable to type 'B extends string ? keyof B : number'.
58+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
59+
b = a;
7260
}
7361

7462
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
@@ -77,11 +65,22 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
7765
!!! error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
7866
!!! error TS2322: Types of property 'foo' are incompatible.
7967
!!! error TS2322: Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'.
68+
!!! error TS2322: Type 'keyof B' is not assignable to type 'keyof A'.
69+
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'keyof A'.
70+
!!! error TS2322: Type 'string' is not assignable to type 'keyof A'.
71+
!!! error TS2322: Type 'string' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
72+
!!! error TS2322: Type 'keyof B' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
73+
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
74+
!!! error TS2322: Type 'string' is not assignable to type 'number | "toString" | "charAt" | "charCodeAt" | "concat" | "indexOf" | "lastIndexOf" | "localeCompare" | "match" | "replace" | "search" | "slice" | "split" | "substring" | "toLowerCase" | "toLocaleLowerCase" | "toUpperCase" | "toLocaleUpperCase" | "trim" | "length" | "substr" | "valueOf"'.
75+
!!! error TS2322: Type 'keyof B' is not assignable to type '"valueOf"'.
76+
!!! error TS2322: Type 'string | number | symbol' is not assignable to type '"valueOf"'.
77+
!!! error TS2322: Type 'string' is not assignable to type '"valueOf"'.
8078
b = a; // Error
8179
~
8280
!!! error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
8381
!!! error TS2322: Types of property 'foo' are incompatible.
8482
!!! error TS2322: Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'.
83+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
8584
}
8685

8786
// Extract<T, Function> is a T that is known to be a Function
@@ -135,20 +134,52 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
135134
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
136135
!!! error TS2345: Type 'Extract<Foo & T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
137136
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
138-
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:64:43: 'bat' is declared here.
139-
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:64:43: 'bat' is declared here.
137+
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
138+
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
140139
fooBat(y); // Error
141140
~
142141
!!! error TS2345: Argument of type 'Extract<T, Foo & Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
143142
!!! error TS2345: Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
144-
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:64:43: 'bat' is declared here.
143+
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
145144
fooBat(z); // Error
146145
~
147146
!!! error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
148147
!!! error TS2345: Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
149148
!!! error TS2345: Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
150149
}
151150

151+
// Repros from #22860
152+
153+
class Opt<T> {
154+
toVector(): Vector<T> {
155+
return <any>undefined;
156+
}
157+
}
158+
159+
interface Seq<T> {
160+
tail(): Opt<Seq<T>>;
161+
}
162+
163+
class Vector<T> implements Seq<T> {
164+
tail(): Opt<Vector<T>> {
165+
return <any>undefined;
166+
}
167+
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
168+
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
169+
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
170+
return <any>undefined;
171+
}
172+
}
173+
174+
interface A1<T> {
175+
bat: B1<A1<T>>;
176+
}
177+
178+
interface B1<T> extends A1<T> {
179+
bat: B1<B1<T>>;
180+
boom: T extends any ? true : true
181+
}
182+
152183
// Repro from #22899
153184

154185
declare function toString1(value: object | Function): string ;
@@ -229,29 +260,4 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
229260
};
230261
type PCCA = ProductComplementComplement['a'];
231262
type PCCB = ProductComplementComplement['b'];
232-
233-
// Repros from #27118
234-
235-
type MyElement<A> = [A] extends [[infer E]] ? E : never;
236-
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> {
237-
return arg; // Unsound, should be error
238-
~~~~~~~~~~~
239-
!!! error TS2322: Type 'MyElement<A>' is not assignable to type 'MyElement<B>'.
240-
}
241-
242-
type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
243-
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> {
244-
return arg; // Unsound, should be error
245-
~~~~~~~~~~~
246-
!!! error TS2322: Type 'MyAcceptor<B>' is not assignable to type 'MyAcceptor<A>'.
247-
}
248-
249-
type Dist<T> = T extends number ? number : string;
250-
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
251-
type Nondist<T> = Aux<{a: T}>;
252-
function oops3<T>(arg: Dist<T>): Nondist<T> {
253-
return arg; // Unsound, should be error
254-
~~~~~~~~~~~
255-
!!! error TS2322: Type 'Dist<T>' is not assignable to type 'Aux<{ a: T; }>'.
256-
}
257263

0 commit comments

Comments
 (0)