Make the assignability rule for conditional types require the check
types and distributivity to be identical. Fixes #27118.
This commit is contained in:
parent
bbf559b9c7
commit
1aca1dd036
6 changed files with 607 additions and 687 deletions
|
@ -12693,10 +12693,11 @@ namespace ts {
|
|||
else if (source.flags & TypeFlags.Conditional) {
|
||||
if (target.flags & TypeFlags.Conditional) {
|
||||
// Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if
|
||||
// one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2,
|
||||
// and Y1 is related to Y2.
|
||||
if (isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
|
||||
(isRelatedTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) || isRelatedTo((<ConditionalType>target).checkType, (<ConditionalType>source).checkType))) {
|
||||
// they have the same distributivity, T1 and T2 are identical types, U1 and U2 are identical
|
||||
// types, X1 is related to X2, and Y1 is related to Y2.
|
||||
if ((<ConditionalType>source).root.isDistributive === (<ConditionalType>target).root.isDistributive &&
|
||||
isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType) &&
|
||||
isTypeIdenticalTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType)) {
|
||||
if (result = isRelatedTo(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target), reportErrors)) {
|
||||
result &= isRelatedTo(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target), reportErrors);
|
||||
}
|
||||
|
|
|
@ -1,29 +1,38 @@
|
|||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(15,5): error TS2322: Type 'Covariant<A>' is not assignable to type 'Covariant<B>'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(19,5): error TS2322: Type 'Contravariant<B>' is not assignable to type 'Contravariant<A>'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(24,5): error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(16,5): error TS2322: Type 'Covariant<B>' is not assignable to type 'Covariant<A>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'B extends string ? B : number' is not assignable to type 'A extends string ? A : number'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(17,5): error TS2322: Type 'Covariant<A>' is not assignable to type 'Covariant<B>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'A extends string ? A : number' is not assignable to type 'B extends string ? B : number'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(21,5): error TS2322: Type 'Contravariant<B>' is not assignable to type 'Contravariant<A>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'B extends string ? keyof B : number' is not assignable to type 'A extends string ? keyof A : number'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(22,5): error TS2322: Type 'Contravariant<A>' is not assignable to type 'Contravariant<B>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'A extends string ? keyof A : number' is not assignable to type 'B extends string ? keyof B : number'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(26,5): error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'.
|
||||
Type 'keyof B' is not assignable to type 'keyof A'.
|
||||
Type 'string | number | symbol' is not assignable to type 'keyof A'.
|
||||
Type 'string' is not assignable to type 'keyof A'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,5): error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(27,5): error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
|
||||
Types of property 'foo' are incompatible.
|
||||
Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
Type 'Extract<Foo & T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
|
||||
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; }'.
|
||||
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; }'.
|
||||
Type 'T extends Bar ? T : never' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(165,5): error TS2322: Type 'MyElement<A>' is not assignable to type 'MyElement<B>'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(170,5): error TS2322: Type 'MyAcceptor<B>' is not assignable to type 'MyAcceptor<A>'.
|
||||
tests/cases/conformance/types/conditional/conditionalTypes2.ts(177,5): error TS2322: Type 'Dist<T>' is not assignable to type 'Aux<{ a: T; }>'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (7 errors) ====
|
||||
==== tests/cases/conformance/types/conditional/conditionalTypes2.ts (12 errors) ====
|
||||
// #27118: Conditional types are now invariant in the check type.
|
||||
|
||||
interface Covariant<T> {
|
||||
foo: T extends string ? T : number;
|
||||
}
|
||||
|
@ -37,19 +46,29 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
|||
}
|
||||
|
||||
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
|
||||
a = b;
|
||||
a = b; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Covariant<B>' is not assignable to type 'Covariant<A>'.
|
||||
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'B extends string ? B : number' is not assignable to type 'A extends string ? A : number'.
|
||||
b = a; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Covariant<A>' is not assignable to type 'Covariant<B>'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'A extends string ? A : number' is not assignable to type 'B extends string ? B : number'.
|
||||
}
|
||||
|
||||
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
|
||||
a = b; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Contravariant<B>' is not assignable to type 'Contravariant<A>'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
b = a;
|
||||
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'B extends string ? keyof B : number' is not assignable to type 'A extends string ? keyof A : number'.
|
||||
b = a; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Contravariant<A>' is not assignable to type 'Contravariant<B>'.
|
||||
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'A extends string ? keyof A : number' is not assignable to type 'B extends string ? keyof B : number'.
|
||||
}
|
||||
|
||||
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
|
||||
|
@ -58,15 +77,11 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
|||
!!! error TS2322: Type 'Invariant<B>' is not assignable to type 'Invariant<A>'.
|
||||
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'B extends string ? keyof B : B' is not assignable to type 'A extends string ? keyof A : A'.
|
||||
!!! error TS2322: Type 'keyof B' is not assignable to type 'keyof A'.
|
||||
!!! error TS2322: Type 'string | number | symbol' is not assignable to type 'keyof A'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'keyof A'.
|
||||
b = a; // Error
|
||||
~
|
||||
!!! error TS2322: Type 'Invariant<A>' is not assignable to type 'Invariant<B>'.
|
||||
!!! error TS2322: Types of property 'foo' are incompatible.
|
||||
!!! error TS2322: Type 'A extends string ? keyof A : A' is not assignable to type 'B extends string ? keyof B : B'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
}
|
||||
|
||||
// Extract<T, Function> is a T that is known to be a Function
|
||||
|
@ -120,13 +135,13 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
|||
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Type 'Extract<Foo & T, Bar>' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'.
|
||||
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
|
||||
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
|
||||
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:64:43: 'bat' is declared here.
|
||||
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:64:43: 'bat' is declared here.
|
||||
fooBat(y); // Error
|
||||
~
|
||||
!!! error TS2345: Argument of type 'Extract<T, Foo & Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
|
||||
!!! error TS2345: Property 'bat' is missing in type 'Foo & Bar' but required in type '{ foo: string; bat: string; }'.
|
||||
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here.
|
||||
!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:64:43: 'bat' is declared here.
|
||||
fooBat(z); // Error
|
||||
~
|
||||
!!! error TS2345: Argument of type 'Extract2<T, Foo, Bar>' is not assignable to parameter of type '{ foo: string; bat: string; }'.
|
||||
|
@ -134,38 +149,6 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
|||
!!! error TS2345: Type 'Bar & Foo & T' is not assignable to type '{ foo: string; bat: string; }'.
|
||||
}
|
||||
|
||||
// Repros from #22860
|
||||
|
||||
class Opt<T> {
|
||||
toVector(): Vector<T> {
|
||||
return <any>undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface Seq<T> {
|
||||
tail(): Opt<Seq<T>>;
|
||||
}
|
||||
|
||||
class Vector<T> implements Seq<T> {
|
||||
tail(): Opt<Vector<T>> {
|
||||
return <any>undefined;
|
||||
}
|
||||
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
|
||||
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
|
||||
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
|
||||
return <any>undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface A1<T> {
|
||||
bat: B1<A1<T>>;
|
||||
}
|
||||
|
||||
interface B1<T> extends A1<T> {
|
||||
bat: B1<B1<T>>;
|
||||
boom: T extends any ? true : true
|
||||
}
|
||||
|
||||
// Repro from #22899
|
||||
|
||||
declare function toString1(value: object | Function): string ;
|
||||
|
@ -247,3 +230,28 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
|
|||
type PCCA = ProductComplementComplement['a'];
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
// Repros from #27118
|
||||
|
||||
type MyElement<A> = [A] extends [[infer E]] ? E : never;
|
||||
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> {
|
||||
return arg; // Unsound, should be error
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'MyElement<A>' is not assignable to type 'MyElement<B>'.
|
||||
}
|
||||
|
||||
type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
|
||||
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> {
|
||||
return arg; // Unsound, should be error
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'MyAcceptor<B>' is not assignable to type 'MyAcceptor<A>'.
|
||||
}
|
||||
|
||||
type Dist<T> = T extends number ? number : string;
|
||||
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
|
||||
type Nondist<T> = Aux<{a: T}>;
|
||||
function oops3<T>(arg: Dist<T>): Nondist<T> {
|
||||
return arg; // Unsound, should be error
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'Dist<T>' is not assignable to type 'Aux<{ a: T; }>'.
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
//// [conditionalTypes2.ts]
|
||||
// #27118: Conditional types are now invariant in the check type.
|
||||
|
||||
interface Covariant<T> {
|
||||
foo: T extends string ? T : number;
|
||||
}
|
||||
|
@ -12,13 +14,13 @@ interface Invariant<T> {
|
|||
}
|
||||
|
||||
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
|
||||
a = b;
|
||||
a = b; // Error
|
||||
b = a; // Error
|
||||
}
|
||||
|
||||
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
|
||||
a = b; // Error
|
||||
b = a;
|
||||
b = a; // Error
|
||||
}
|
||||
|
||||
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
|
||||
|
@ -76,38 +78,6 @@ function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: E
|
|||
fooBat(z); // Error
|
||||
}
|
||||
|
||||
// Repros from #22860
|
||||
|
||||
class Opt<T> {
|
||||
toVector(): Vector<T> {
|
||||
return <any>undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface Seq<T> {
|
||||
tail(): Opt<Seq<T>>;
|
||||
}
|
||||
|
||||
class Vector<T> implements Seq<T> {
|
||||
tail(): Opt<Vector<T>> {
|
||||
return <any>undefined;
|
||||
}
|
||||
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
|
||||
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
|
||||
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
|
||||
return <any>undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface A1<T> {
|
||||
bat: B1<A1<T>>;
|
||||
}
|
||||
|
||||
interface B1<T> extends A1<T> {
|
||||
bat: B1<B1<T>>;
|
||||
boom: T extends any ? true : true
|
||||
}
|
||||
|
||||
// Repro from #22899
|
||||
|
||||
declare function toString1(value: object | Function): string ;
|
||||
|
@ -189,16 +159,36 @@ type ProductComplementComplement = {
|
|||
type PCCA = ProductComplementComplement['a'];
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
// Repros from #27118
|
||||
|
||||
type MyElement<A> = [A] extends [[infer E]] ? E : never;
|
||||
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
||||
type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
|
||||
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
||||
type Dist<T> = T extends number ? number : string;
|
||||
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
|
||||
type Nondist<T> = Aux<{a: T}>;
|
||||
function oops3<T>(arg: Dist<T>): Nondist<T> {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
||||
|
||||
//// [conditionalTypes2.js]
|
||||
"use strict";
|
||||
// #27118: Conditional types are now invariant in the check type.
|
||||
function f1(a, b) {
|
||||
a = b;
|
||||
a = b; // Error
|
||||
b = a; // Error
|
||||
}
|
||||
function f2(a, b) {
|
||||
a = b; // Error
|
||||
b = a;
|
||||
b = a; // Error
|
||||
}
|
||||
function f3(a, b) {
|
||||
a = b; // Error
|
||||
|
@ -239,32 +229,21 @@ function f21(x, y, z) {
|
|||
fooBat(y); // Error
|
||||
fooBat(z); // Error
|
||||
}
|
||||
// Repros from #22860
|
||||
var Opt = /** @class */ (function () {
|
||||
function Opt() {
|
||||
}
|
||||
Opt.prototype.toVector = function () {
|
||||
return undefined;
|
||||
};
|
||||
return Opt;
|
||||
}());
|
||||
var Vector = /** @class */ (function () {
|
||||
function Vector() {
|
||||
}
|
||||
Vector.prototype.tail = function () {
|
||||
return undefined;
|
||||
};
|
||||
Vector.prototype.partition2 = function (predicate) {
|
||||
return undefined;
|
||||
};
|
||||
return Vector;
|
||||
}());
|
||||
function foo(value) {
|
||||
if (isFunction(value)) {
|
||||
toString1(value);
|
||||
toString2(value);
|
||||
}
|
||||
}
|
||||
function oops(arg) {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
function oops2(arg) {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
function oops3(arg) {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
||||
|
||||
//// [conditionalTypes2.d.ts]
|
||||
|
@ -302,24 +281,6 @@ declare function fooBat(x: {
|
|||
declare type Extract2<T, U, V> = T extends U ? T extends V ? T : never : never;
|
||||
declare function f20<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: Extract2<T, Foo, Bar>): void;
|
||||
declare function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: Extract2<T, Foo, Bar>): void;
|
||||
declare class Opt<T> {
|
||||
toVector(): Vector<T>;
|
||||
}
|
||||
interface Seq<T> {
|
||||
tail(): Opt<Seq<T>>;
|
||||
}
|
||||
declare class Vector<T> implements Seq<T> {
|
||||
tail(): Opt<Vector<T>>;
|
||||
partition2<U extends T>(predicate: (v: T) => v is U): [Vector<U>, Vector<Exclude<T, U>>];
|
||||
partition2(predicate: (x: T) => boolean): [Vector<T>, Vector<T>];
|
||||
}
|
||||
interface A1<T> {
|
||||
bat: B1<A1<T>>;
|
||||
}
|
||||
interface B1<T> extends A1<T> {
|
||||
bat: B1<B1<T>>;
|
||||
boom: T extends any ? true : true;
|
||||
}
|
||||
declare function toString1(value: object | Function): string;
|
||||
declare function toString2(value: Function): string;
|
||||
declare function foo<T>(value: T): void;
|
||||
|
@ -392,3 +353,15 @@ declare type ProductComplementComplement = {
|
|||
};
|
||||
declare type PCCA = ProductComplementComplement['a'];
|
||||
declare type PCCB = ProductComplementComplement['b'];
|
||||
declare type MyElement<A> = [A] extends [[infer E]] ? E : never;
|
||||
declare function oops<A, B extends A>(arg: MyElement<A>): MyElement<B>;
|
||||
declare type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
|
||||
declare function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A>;
|
||||
declare type Dist<T> = T extends number ? number : string;
|
||||
declare type Aux<A extends {
|
||||
a: unknown;
|
||||
}> = A["a"] extends number ? number : string;
|
||||
declare type Nondist<T> = Aux<{
|
||||
a: T;
|
||||
}>;
|
||||
declare function oops3<T>(arg: Dist<T>): Nondist<T>;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,6 @@
|
|||
=== tests/cases/conformance/types/conditional/conditionalTypes2.ts ===
|
||||
// #27118: Conditional types are now invariant in the check type.
|
||||
|
||||
interface Covariant<T> {
|
||||
foo: T extends string ? T : number;
|
||||
>foo : T extends string ? T : number
|
||||
|
@ -19,7 +21,7 @@ function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
|
|||
>a : Covariant<A>
|
||||
>b : Covariant<B>
|
||||
|
||||
a = b;
|
||||
a = b; // Error
|
||||
>a = b : Covariant<B>
|
||||
>a : Covariant<A>
|
||||
>b : Covariant<B>
|
||||
|
@ -40,7 +42,7 @@ function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
|
|||
>a : Contravariant<A>
|
||||
>b : Contravariant<B>
|
||||
|
||||
b = a;
|
||||
b = a; // Error
|
||||
>b = a : Contravariant<A>
|
||||
>b : Contravariant<B>
|
||||
>a : Contravariant<A>
|
||||
|
@ -207,71 +209,6 @@ function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: E
|
|||
>z : Extract2<T, Foo, Bar>
|
||||
}
|
||||
|
||||
// Repros from #22860
|
||||
|
||||
class Opt<T> {
|
||||
>Opt : Opt<T>
|
||||
|
||||
toVector(): Vector<T> {
|
||||
>toVector : () => Vector<T>
|
||||
|
||||
return <any>undefined;
|
||||
><any>undefined : any
|
||||
>undefined : undefined
|
||||
}
|
||||
}
|
||||
|
||||
interface Seq<T> {
|
||||
tail(): Opt<Seq<T>>;
|
||||
>tail : () => Opt<Seq<T>>
|
||||
}
|
||||
|
||||
class Vector<T> implements Seq<T> {
|
||||
>Vector : Vector<T>
|
||||
|
||||
tail(): Opt<Vector<T>> {
|
||||
>tail : () => Opt<Vector<T>>
|
||||
|
||||
return <any>undefined;
|
||||
><any>undefined : any
|
||||
>undefined : undefined
|
||||
}
|
||||
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
|
||||
>partition2 : { <U extends T>(predicate: (v: T) => v is U): [Vector<U>, Vector<Exclude<T, U>>]; (predicate: (x: T) => boolean): [Vector<T>, Vector<T>]; }
|
||||
>predicate : (v: T) => v is U
|
||||
>v : T
|
||||
|
||||
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
|
||||
>partition2 : { <U extends T>(predicate: (v: T) => v is U): [Vector<U>, Vector<Exclude<T, U>>]; (predicate: (x: T) => boolean): [Vector<T>, Vector<T>]; }
|
||||
>predicate : (x: T) => boolean
|
||||
>x : T
|
||||
|
||||
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
|
||||
>partition2 : { <U extends T>(predicate: (v: T) => v is U): [Vector<U>, Vector<Exclude<T, U>>]; (predicate: (x: T) => boolean): [Vector<T>, Vector<T>]; }
|
||||
>predicate : (v: T) => boolean
|
||||
>v : T
|
||||
|
||||
return <any>undefined;
|
||||
><any>undefined : any
|
||||
>undefined : undefined
|
||||
}
|
||||
}
|
||||
|
||||
interface A1<T> {
|
||||
bat: B1<A1<T>>;
|
||||
>bat : B1<A1<T>>
|
||||
}
|
||||
|
||||
interface B1<T> extends A1<T> {
|
||||
bat: B1<B1<T>>;
|
||||
>bat : B1<B1<T>>
|
||||
|
||||
boom: T extends any ? true : true
|
||||
>boom : T extends any ? true : true
|
||||
>true : true
|
||||
>true : true
|
||||
}
|
||||
|
||||
// Repro from #22899
|
||||
|
||||
declare function toString1(value: object | Function): string ;
|
||||
|
@ -431,3 +368,47 @@ type PCCA = ProductComplementComplement['a'];
|
|||
type PCCB = ProductComplementComplement['b'];
|
||||
>PCCB : Product<"b", 1>
|
||||
|
||||
// Repros from #27118
|
||||
|
||||
type MyElement<A> = [A] extends [[infer E]] ? E : never;
|
||||
>MyElement : MyElement<A>
|
||||
|
||||
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> {
|
||||
>oops : <A, B extends A>(arg: MyElement<A>) => MyElement<B>
|
||||
>arg : MyElement<A>
|
||||
|
||||
return arg; // Unsound, should be error
|
||||
>arg : MyElement<A>
|
||||
}
|
||||
|
||||
type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
|
||||
>MyAcceptor : MyAcceptor<A>
|
||||
>arg : E
|
||||
|
||||
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> {
|
||||
>oops2 : <A, B extends A>(arg: MyAcceptor<B>) => MyAcceptor<A>
|
||||
>arg : MyAcceptor<B>
|
||||
|
||||
return arg; // Unsound, should be error
|
||||
>arg : MyAcceptor<B>
|
||||
}
|
||||
|
||||
type Dist<T> = T extends number ? number : string;
|
||||
>Dist : Dist<T>
|
||||
|
||||
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
|
||||
>Aux : Aux<A>
|
||||
>a : unknown
|
||||
|
||||
type Nondist<T> = Aux<{a: T}>;
|
||||
>Nondist : Aux<{ a: T; }>
|
||||
>a : T
|
||||
|
||||
function oops3<T>(arg: Dist<T>): Nondist<T> {
|
||||
>oops3 : <T>(arg: Dist<T>) => Aux<{ a: T; }>
|
||||
>arg : Dist<T>
|
||||
|
||||
return arg; // Unsound, should be error
|
||||
>arg : Dist<T>
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// @strict: true
|
||||
// @declaration: true
|
||||
|
||||
// #27118: Conditional types are now invariant in the check type.
|
||||
|
||||
interface Covariant<T> {
|
||||
foo: T extends string ? T : number;
|
||||
}
|
||||
|
@ -14,13 +16,13 @@ interface Invariant<T> {
|
|||
}
|
||||
|
||||
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
|
||||
a = b;
|
||||
a = b; // Error
|
||||
b = a; // Error
|
||||
}
|
||||
|
||||
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
|
||||
a = b; // Error
|
||||
b = a;
|
||||
b = a; // Error
|
||||
}
|
||||
|
||||
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
|
||||
|
@ -78,38 +80,6 @@ function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: E
|
|||
fooBat(z); // Error
|
||||
}
|
||||
|
||||
// Repros from #22860
|
||||
|
||||
class Opt<T> {
|
||||
toVector(): Vector<T> {
|
||||
return <any>undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface Seq<T> {
|
||||
tail(): Opt<Seq<T>>;
|
||||
}
|
||||
|
||||
class Vector<T> implements Seq<T> {
|
||||
tail(): Opt<Vector<T>> {
|
||||
return <any>undefined;
|
||||
}
|
||||
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
|
||||
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
|
||||
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
|
||||
return <any>undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface A1<T> {
|
||||
bat: B1<A1<T>>;
|
||||
}
|
||||
|
||||
interface B1<T> extends A1<T> {
|
||||
bat: B1<B1<T>>;
|
||||
boom: T extends any ? true : true
|
||||
}
|
||||
|
||||
// Repro from #22899
|
||||
|
||||
declare function toString1(value: object | Function): string ;
|
||||
|
@ -190,3 +160,22 @@ type ProductComplementComplement = {
|
|||
};
|
||||
type PCCA = ProductComplementComplement['a'];
|
||||
type PCCB = ProductComplementComplement['b'];
|
||||
|
||||
// Repros from #27118
|
||||
|
||||
type MyElement<A> = [A] extends [[infer E]] ? E : never;
|
||||
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
||||
type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
|
||||
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
||||
type Dist<T> = T extends number ? number : string;
|
||||
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
|
||||
type Nondist<T> = Aux<{a: T}>;
|
||||
function oops3<T>(arg: Dist<T>): Nondist<T> {
|
||||
return arg; // Unsound, should be error
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue