Merge pull request #22869 from Microsoft/fixConditionalTypeVariance

Fix conditional type variance
This commit is contained in:
Anders Hejlsberg
2018-03-26 09:36:16 -07:00
committed by GitHub
6 changed files with 709 additions and 2 deletions

View File

@@ -10200,8 +10200,11 @@ namespace ts {
}
else if (source.flags & TypeFlags.Conditional) {
if (target.flags & TypeFlags.Conditional) {
if (isTypeIdenticalTo((<ConditionalType>source).checkType, (<ConditionalType>target).checkType) &&
isTypeIdenticalTo((<ConditionalType>source).extendsType, (<ConditionalType>target).extendsType)) {
// 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))) {
if (result = isRelatedTo(getTrueTypeFromConditionalType(<ConditionalType>source), getTrueTypeFromConditionalType(<ConditionalType>target), reportErrors)) {
result &= isRelatedTo(getFalseTypeFromConditionalType(<ConditionalType>source), getFalseTypeFromConditionalType(<ConditionalType>target), reportErrors);
}

View File

@@ -0,0 +1,90 @@
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>'.
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'.
tests/cases/conformance/types/conditional/conditionalTypes2.ts(25,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 (4 errors) ====
interface Covariant<T> {
foo: T extends string ? T : number;
}
interface Contravariant<T> {
foo: T extends string ? keyof T : number;
}
interface Invariant<T> {
foo: T extends string ? keyof T : T;
}
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
a = b;
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'.
}
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;
}
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
a = b; // Error
~
!!! 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'.
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'.
}
// 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
}

View File

@@ -0,0 +1,128 @@
//// [conditionalTypes2.ts]
interface Covariant<T> {
foo: T extends string ? T : number;
}
interface Contravariant<T> {
foo: T extends string ? keyof T : number;
}
interface Invariant<T> {
foo: T extends string ? keyof T : T;
}
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
a = b;
b = a; // Error
}
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
a = b; // Error
b = a;
}
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
a = b; // Error
b = a; // 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
}
//// [conditionalTypes2.js]
"use strict";
function f1(a, b) {
a = b;
b = a; // Error
}
function f2(a, b) {
a = b; // Error
b = a;
}
function f3(a, b) {
a = b; // Error
b = a; // 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;
}());
//// [conditionalTypes2.d.ts]
interface Covariant<T> {
foo: T extends string ? T : number;
}
interface Contravariant<T> {
foo: T extends string ? keyof T : number;
}
interface Invariant<T> {
foo: T extends string ? keyof T : T;
}
declare function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>): void;
declare function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>): void;
declare function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>): 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;
}

View File

@@ -0,0 +1,207 @@
=== tests/cases/conformance/types/conditional/conditionalTypes2.ts ===
interface Covariant<T> {
>Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0))
>T : Symbol(T, Decl(conditionalTypes2.ts, 0, 20))
foo: T extends string ? T : number;
>foo : Symbol(Covariant.foo, Decl(conditionalTypes2.ts, 0, 24))
>T : Symbol(T, Decl(conditionalTypes2.ts, 0, 20))
>T : Symbol(T, Decl(conditionalTypes2.ts, 0, 20))
}
interface Contravariant<T> {
>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 4, 24))
foo: T extends string ? keyof T : number;
>foo : Symbol(Contravariant.foo, Decl(conditionalTypes2.ts, 4, 28))
>T : Symbol(T, Decl(conditionalTypes2.ts, 4, 24))
>T : Symbol(T, Decl(conditionalTypes2.ts, 4, 24))
}
interface Invariant<T> {
>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20))
foo: T extends string ? keyof T : T;
>foo : Symbol(Invariant.foo, Decl(conditionalTypes2.ts, 8, 24))
>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20))
>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20))
>T : Symbol(T, Decl(conditionalTypes2.ts, 8, 20))
}
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
>f1 : Symbol(f1, Decl(conditionalTypes2.ts, 10, 1))
>A : Symbol(A, Decl(conditionalTypes2.ts, 12, 12))
>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 14))
>A : Symbol(A, Decl(conditionalTypes2.ts, 12, 12))
>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28))
>Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0))
>A : Symbol(A, Decl(conditionalTypes2.ts, 12, 12))
>b : Symbol(b, Decl(conditionalTypes2.ts, 12, 44))
>Covariant : Symbol(Covariant, Decl(conditionalTypes2.ts, 0, 0))
>B : Symbol(B, Decl(conditionalTypes2.ts, 12, 14))
a = b;
>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28))
>b : Symbol(b, Decl(conditionalTypes2.ts, 12, 44))
b = a; // Error
>b : Symbol(b, Decl(conditionalTypes2.ts, 12, 44))
>a : Symbol(a, Decl(conditionalTypes2.ts, 12, 28))
}
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
>f2 : Symbol(f2, Decl(conditionalTypes2.ts, 15, 1))
>A : Symbol(A, Decl(conditionalTypes2.ts, 17, 12))
>B : Symbol(B, Decl(conditionalTypes2.ts, 17, 14))
>A : Symbol(A, Decl(conditionalTypes2.ts, 17, 12))
>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28))
>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1))
>A : Symbol(A, Decl(conditionalTypes2.ts, 17, 12))
>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48))
>Contravariant : Symbol(Contravariant, Decl(conditionalTypes2.ts, 2, 1))
>B : Symbol(B, Decl(conditionalTypes2.ts, 17, 14))
a = b; // Error
>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28))
>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48))
b = a;
>b : Symbol(b, Decl(conditionalTypes2.ts, 17, 48))
>a : Symbol(a, Decl(conditionalTypes2.ts, 17, 28))
}
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
>f3 : Symbol(f3, Decl(conditionalTypes2.ts, 20, 1))
>A : Symbol(A, Decl(conditionalTypes2.ts, 22, 12))
>B : Symbol(B, Decl(conditionalTypes2.ts, 22, 14))
>A : Symbol(A, Decl(conditionalTypes2.ts, 22, 12))
>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28))
>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1))
>A : Symbol(A, Decl(conditionalTypes2.ts, 22, 12))
>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44))
>Invariant : Symbol(Invariant, Decl(conditionalTypes2.ts, 6, 1))
>B : Symbol(B, Decl(conditionalTypes2.ts, 22, 14))
a = b; // Error
>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28))
>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44))
b = a; // Error
>b : Symbol(b, Decl(conditionalTypes2.ts, 22, 44))
>a : Symbol(a, Decl(conditionalTypes2.ts, 22, 28))
}
// Repros from #22860
class Opt<T> {
>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 25, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 29, 10))
toVector(): Vector<T> {
>toVector : Symbol(Opt.toVector, Decl(conditionalTypes2.ts, 29, 14))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 29, 10))
return <any>undefined;
>undefined : Symbol(undefined)
}
}
interface Seq<T> {
>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 33, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 35, 14))
tail(): Opt<Seq<T>>;
>tail : Symbol(Seq.tail, Decl(conditionalTypes2.ts, 35, 18))
>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 25, 1))
>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 33, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 35, 14))
}
class Vector<T> implements Seq<T> {
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>Seq : Symbol(Seq, Decl(conditionalTypes2.ts, 33, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
tail(): Opt<Vector<T>> {
>tail : Symbol(Vector.tail, Decl(conditionalTypes2.ts, 39, 35))
>Opt : Symbol(Opt, Decl(conditionalTypes2.ts, 25, 1))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
return <any>undefined;
>undefined : Symbol(undefined)
}
partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>];
>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 42, 5), Decl(conditionalTypes2.ts, 43, 88), Decl(conditionalTypes2.ts, 44, 64))
>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 43, 28))
>v : Symbol(v, Decl(conditionalTypes2.ts, 43, 39))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>v : Symbol(v, Decl(conditionalTypes2.ts, 43, 39))
>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>Exclude : Symbol(Exclude, Decl(lib.d.ts, --, --))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>U : Symbol(U, Decl(conditionalTypes2.ts, 43, 15))
partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>];
>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 42, 5), Decl(conditionalTypes2.ts, 43, 88), Decl(conditionalTypes2.ts, 44, 64))
>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 44, 15))
>x : Symbol(x, Decl(conditionalTypes2.ts, 44, 26))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] {
>partition2 : Symbol(Vector.partition2, Decl(conditionalTypes2.ts, 42, 5), Decl(conditionalTypes2.ts, 43, 88), Decl(conditionalTypes2.ts, 44, 64))
>U : Symbol(U, Decl(conditionalTypes2.ts, 45, 15))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>predicate : Symbol(predicate, Decl(conditionalTypes2.ts, 45, 28))
>v : Symbol(v, Decl(conditionalTypes2.ts, 45, 39))
>T : Symbol(T, Decl(conditionalTypes2.ts, 39, 13))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
>U : Symbol(U, Decl(conditionalTypes2.ts, 45, 15))
>Vector : Symbol(Vector, Decl(conditionalTypes2.ts, 37, 1))
return <any>undefined;
>undefined : Symbol(undefined)
}
}
interface A1<T> {
>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 48, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 50, 13))
bat: B1<A1<T>>;
>bat : Symbol(A1.bat, Decl(conditionalTypes2.ts, 50, 17))
>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1))
>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 48, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 50, 13))
}
interface B1<T> extends A1<T> {
>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13))
>A1 : Symbol(A1, Decl(conditionalTypes2.ts, 48, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13))
bat: B1<B1<T>>;
>bat : Symbol(B1.bat, Decl(conditionalTypes2.ts, 54, 31))
>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1))
>B1 : Symbol(B1, Decl(conditionalTypes2.ts, 52, 1))
>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13))
boom: T extends any ? true : true
>boom : Symbol(B1.boom, Decl(conditionalTypes2.ts, 55, 19))
>T : Symbol(T, Decl(conditionalTypes2.ts, 54, 13))
}

View File

@@ -0,0 +1,218 @@
=== tests/cases/conformance/types/conditional/conditionalTypes2.ts ===
interface Covariant<T> {
>Covariant : Covariant<T>
>T : T
foo: T extends string ? T : number;
>foo : T extends string ? T : number
>T : T
>T : T
}
interface Contravariant<T> {
>Contravariant : Contravariant<T>
>T : T
foo: T extends string ? keyof T : number;
>foo : T extends string ? keyof T : number
>T : T
>T : T
}
interface Invariant<T> {
>Invariant : Invariant<T>
>T : T
foo: T extends string ? keyof T : T;
>foo : T extends string ? keyof T : T
>T : T
>T : T
>T : T
}
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
>f1 : <A, B extends A>(a: Covariant<A>, b: Covariant<B>) => void
>A : A
>B : B
>A : A
>a : Covariant<A>
>Covariant : Covariant<T>
>A : A
>b : Covariant<B>
>Covariant : Covariant<T>
>B : B
a = b;
>a = b : Covariant<B>
>a : Covariant<A>
>b : Covariant<B>
b = a; // Error
>b = a : Covariant<A>
>b : Covariant<B>
>a : Covariant<A>
}
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
>f2 : <A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) => void
>A : A
>B : B
>A : A
>a : Contravariant<A>
>Contravariant : Contravariant<T>
>A : A
>b : Contravariant<B>
>Contravariant : Contravariant<T>
>B : B
a = b; // Error
>a = b : Contravariant<B>
>a : Contravariant<A>
>b : Contravariant<B>
b = a;
>b = a : Contravariant<A>
>b : Contravariant<B>
>a : Contravariant<A>
}
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
>f3 : <A, B extends A>(a: Invariant<A>, b: Invariant<B>) => void
>A : A
>B : B
>A : A
>a : Invariant<A>
>Invariant : Invariant<T>
>A : A
>b : Invariant<B>
>Invariant : Invariant<T>
>B : B
a = b; // Error
>a = b : Invariant<B>
>a : Invariant<A>
>b : Invariant<B>
b = a; // Error
>b = a : Invariant<A>
>b : Invariant<B>
>a : Invariant<A>
}
// Repros from #22860
class Opt<T> {
>Opt : Opt<T>
>T : T
toVector(): Vector<T> {
>toVector : () => Vector<T>
>Vector : Vector<T>
>T : T
return <any>undefined;
><any>undefined : any
>undefined : undefined
}
}
interface Seq<T> {
>Seq : Seq<T>
>T : T
tail(): Opt<Seq<T>>;
>tail : () => Opt<Seq<T>>
>Opt : Opt<T>
>Seq : Seq<T>
>T : T
}
class Vector<T> implements Seq<T> {
>Vector : Vector<T>
>T : T
>Seq : Seq<T>
>T : T
tail(): Opt<Vector<T>> {
>tail : () => Opt<Vector<T>>
>Opt : Opt<T>
>Vector : Vector<T>
>T : 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>]; }
>U : U
>T : T
>predicate : (v: T) => v is U
>v : T
>T : T
>v : any
>U : U
>Vector : Vector<T>
>U : U
>Vector : Vector<T>
>Exclude : Exclude<T, U>
>T : T
>U : U
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
>T : T
>Vector : Vector<T>
>T : T
>Vector : Vector<T>
>T : 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>]; }
>U : U
>T : T
>predicate : (v: T) => boolean
>v : T
>T : T
>Vector : Vector<T>
>U : U
>Vector : Vector<T>
return <any>undefined;
><any>undefined : any
>undefined : undefined
}
}
interface A1<T> {
>A1 : A1<T>
>T : T
bat: B1<A1<T>>;
>bat : B1<A1<T>>
>B1 : B1<T>
>A1 : A1<T>
>T : T
}
interface B1<T> extends A1<T> {
>B1 : B1<T>
>T : T
>A1 : A1<T>
>T : T
bat: B1<B1<T>>;
>bat : B1<B1<T>>
>B1 : B1<T>
>B1 : B1<T>
>T : T
boom: T extends any ? true : true
>boom : T extends any ? true : true
>T : T
>true : true
>true : true
}

View File

@@ -0,0 +1,61 @@
// @strict: true
// @declaration: true
interface Covariant<T> {
foo: T extends string ? T : number;
}
interface Contravariant<T> {
foo: T extends string ? keyof T : number;
}
interface Invariant<T> {
foo: T extends string ? keyof T : T;
}
function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) {
a = b;
b = a; // Error
}
function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) {
a = b; // Error
b = a;
}
function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) {
a = b; // Error
b = a; // 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
}