Make the assignability rule for conditional types require the check

types and distributivity to be identical.

Fixes #27118.
This commit is contained in:
Matt McCutchen 2018-10-10 19:30:50 -04:00
parent bbf559b9c7
commit 1aca1dd036
6 changed files with 607 additions and 687 deletions

View file

@ -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);
}

View file

@ -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 ;
@ -246,4 +229,29 @@ 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; }>'.
}

View file

@ -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 ;
@ -188,17 +158,37 @@ 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

View file

@ -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>
}

View file

@ -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
}