Skip to content

Commit aedffe0

Browse files
committed
Revert "Merge pull request #27697 from mattmccutchen/issue-27118"
This reverts commit 2dfb620, reversing changes made to bbf559b.
1 parent 4718ff8 commit aedffe0

File tree

6 files changed

+687
-607
lines changed

6 files changed

+687
-607
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 5 deletions
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

Lines changed: 57 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,29 @@
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+
tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,5): error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
1712
Types of property 'foo' are incompatible.
1813
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; }'.
14+
Type 'A' is not assignable to type 'B'.
15+
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; }'.
2016
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
2117
Type 'Extract<Foo & T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
2218
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; }'.
19+
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; }'.
2420
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; }'.
21+
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; }'.
2622
Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
2723
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; }>'.
3124

3225

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

4839
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'.
40+
a = b;
5441
b = a; // Error
5542
~
5643
!!! 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'.
44+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
5945
}
6046

6147
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
6248
a = b; // Error
6349
~
6450
!!! 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'.
51+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
52+
b = a;
7253
}
7354

7455
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
@@ -77,11 +58,15 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
7758
!!! error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
7859
!!! error TS2322: Types of property 'foo' are incompatible.
7960
!!! error TS2322: Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'.
61+
!!! error TS2322: Type 'keyof B' is not assignable to type 'keyof A'.
62+
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'keyof A'.
63+
!!! error TS2322: Type 'string' is not assignable to type 'keyof A'.
8064
b = a; // Error
8165
~
8266
!!! error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
8367
!!! error TS2322: Types of property 'foo' are incompatible.
8468
!!! error TS2322: Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'.
69+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
8570
}
8671

8772
// Extract<T, Function> is a T that is known to be a Function
@@ -135,20 +120,52 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
135120
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
136121
!!! error TS2345: Type 'Extract<Foo & T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
137122
!!! 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.
123+
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
124+
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
140125
fooBat(y); // Error
141126
~
142127
!!! error TS2345: Argument of type 'Extract<T, Foo & Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
143128
!!! 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.
129+
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
145130
fooBat(z); // Error
146131
~
147132
!!! error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
148133
!!! error TS2345: Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
149134
!!! error TS2345: Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
150135
}
151136

137+
// Repros from #22860
138+
139+
class Opt<T> {
140+
toVector(): Vector<T> {
141+
return <any>undefined;
142+
}
143+
}
144+
145+
interface Seq<T> {
146+
tail(): Opt<Seq<T>>;
147+
}
148+
149+
class Vector<T> implements Seq<T> {
150+
tail(): Opt<Vector<T>> {
151+
return <any>undefined;
152+
}
153+
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
154+
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
155+
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
156+
return <any>undefined;
157+
}
158+
}
159+
160+
interface A1<T> {
161+
bat: B1<A1<T>>;
162+
}
163+
164+
interface B1<T> extends A1<T> {
165+
bat: B1<B1<T>>;
166+
boom: T extends any ? true : true
167+
}
168+
152169
// Repro from #22899
153170

154171
declare function toString1(value: object | Function): string ;
@@ -229,29 +246,4 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2
229246
};
230247
type PCCA = ProductComplementComplement['a'];
231248
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-
}
257249

tests/baselines/reference/conditionalTypes2.js

Lines changed: 74 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
//// [conditionalTypes2.ts]
2-
// #27118: Conditional types are now invariant in the check type.
3-
42
interface Covariant<T> {
53
foo: T extends string ? T : number;
64
}
@@ -14,13 +12,13 @@ interface Invariant<T> {
1412
}
1513

1614
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
17-
a = b; // Error
15+
a = b;
1816
b = a; // Error
1917
}
2018

2119
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
2220
a = b; // Error
23-
b = a; // Error
21+
b = a;
2422
}
2523

2624
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
@@ -78,6 +76,38 @@ function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: E
7876
fooBat(z); // Error
7977
}
8078

79+
// Repros from #22860
80+
81+
class Opt<T> {
82+
toVector(): Vector<T> {
83+
return <any>undefined;
84+
}
85+
}
86+
87+
interface Seq<T> {
88+
tail(): Opt<Seq<T>>;
89+
}
90+
91+
class Vector<T> implements Seq<T> {
92+
tail(): Opt<Vector<T>> {
93+
return <any>undefined;
94+
}
95+
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
96+
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
97+
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
98+
return <any>undefined;
99+
}
100+
}
101+
102+
interface A1<T> {
103+
bat: B1<A1<T>>;
104+
}
105+
106+
interface B1<T> extends A1<T> {
107+
bat: B1<B1<T>>;
108+
boom: T extends any ? true : true
109+
}
110+
81111
// Repro from #22899
82112

83113
declare function toString1(value: object | Function): string ;
@@ -158,37 +188,17 @@ type ProductComplementComplement = {
158188
};
159189
type PCCA = ProductComplementComplement['a'];
160190
type PCCB = ProductComplementComplement['b'];
161-
162-
// Repros from #27118
163-
164-
type MyElement<A> = [A] extends [[infer E]] ? E : never;
165-
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> {
166-
return arg; // Unsound, should be error
167-
}
168-
169-
type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
170-
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> {
171-
return arg; // Unsound, should be error
172-
}
173-
174-
type Dist<T> = T extends number ? number : string;
175-
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
176-
type Nondist<T> = Aux<{a: T}>;
177-
function oops3<T>(arg: Dist<T>): Nondist<T> {
178-
return arg; // Unsound, should be error
179-
}
180191

181192

182193
//// [conditionalTypes2.js]
183194
"use strict";
184-
// #27118: Conditional types are now invariant in the check type.
185195
function f1(a, b) {
186-
a = b; // Error
196+
a = b;
187197
b = a; // Error
188198
}
189199
function f2(a, b) {
190200
a = b; // Error
191-
b = a; // Error
201+
b = a;
192202
}
193203
function f3(a, b) {
194204
a = b; // Error
@@ -229,21 +239,32 @@ function f21(x, y, z) {
229239
fooBat(y); // Error
230240
fooBat(z); // Error
231241
}
242+
// Repros from #22860
243+
var Opt = /** @class */ (function () {
244+
function Opt() {
245+
}
246+
Opt.prototype.toVector = function () {
247+
return undefined;
248+
};
249+
return Opt;
250+
}());
251+
var Vector = /** @class */ (function () {
252+
function Vector() {
253+
}
254+
Vector.prototype.tail = function () {
255+
return undefined;
256+
};
257+
Vector.prototype.partition2 = function (predicate) {
258+
return undefined;
259+
};
260+
return Vector;
261+
}());
232262
function foo(value) {
233263
if (isFunction(value)) {
234264
toString1(value);
235265
toString2(value);
236266
}
237267
}
238-
function oops(arg) {
239-
return arg; // Unsound, should be error
240-
}
241-
function oops2(arg) {
242-
return arg; // Unsound, should be error
243-
}
244-
function oops3(arg) {
245-
return arg; // Unsound, should be error
246-
}
247268

248269

249270
//// [conditionalTypes2.d.ts]
@@ -281,6 +302,24 @@ declare function fooBat(x: {
281302
declare type Extract2<T, U, V> = T extends U ? T extends V ? T : never : never;
282303
declare function f20<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: Extract2<T, Foo, Bar>): void;
283304
declare function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: Extract2<T, Foo, Bar>): void;
305+
declare class Opt<T> {
306+
toVector(): Vector<T>;
307+
}
308+
interface Seq<T> {
309+
tail(): Opt<Seq<T>>;
310+
}
311+
declare class Vector<T> implements Seq<T> {
312+
tail(): Opt<Vector<T>>;
313+
partition2<U extends T>(predicate: (v: T) => v is U): [Vector<U>, Vector<Exclude<T, U>>];
314+
partition2(predicate: (x: T) => boolean): [Vector<T>, Vector<T>];
315+
}
316+
interface A1<T> {
317+
bat: B1<A1<T>>;
318+
}
319+
interface B1<T> extends A1<T> {
320+
bat: B1<B1<T>>;
321+
boom: T extends any ? true : true;
322+
}
284323
declare function toString1(value: object | Function): string;
285324
declare function toString2(value: Function): string;
286325
declare function foo<T>(value: T): void;
@@ -353,15 +392,3 @@ declare type ProductComplementComplement = {
353392
};
354393
declare type PCCA = ProductComplementComplement['a'];
355394
declare type PCCB = ProductComplementComplement['b'];
356-
declare type MyElement<A> = [A] extends [[infer E]] ? E : never;
357-
declare function oops<A, B extends A>(arg: MyElement<A>): MyElement<B>;
358-
declare type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
359-
declare function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A>;
360-
declare type Dist<T> = T extends number ? number : string;
361-
declare type Aux<A extends {
362-
a: unknown;
363-
}> = A["a"] extends number ? number : string;
364-
declare type Nondist<T> = Aux<{
365-
a: T;
366-
}>;
367-
declare function oops3<T>(arg: Dist<T>): Nondist<T>;

0 commit comments

Comments
 (0)