1// @strict: true 2// @declaration: true 3 4interface Covariant<T> { 5 foo: T extends string ? T : number; 6} 7 8interface Contravariant<T> { 9 foo: T extends string ? keyof T : number; 10} 11 12interface Invariant<T> { 13 foo: T extends string ? keyof T : T; 14} 15 16function f1<A, B extends A>(a: Covariant<A>, b: Covariant<B>) { 17 a = b; 18 b = a; // Error 19} 20 21function f2<A, B extends A>(a: Contravariant<A>, b: Contravariant<B>) { 22 a = b; // Error 23 b = a; 24} 25 26function f3<A, B extends A>(a: Invariant<A>, b: Invariant<B>) { 27 a = b; // Error 28 b = a; // Error 29} 30 31// Extract<T, Function> is a T that is known to be a Function 32function isFunction<T>(value: T): value is Extract<T, Function> { 33 return typeof value === "function"; 34} 35 36function getFunction<T>(item: T) { 37 if (isFunction(item)) { 38 return item; 39 } 40 throw new Error(); 41} 42 43function f10<T>(x: T) { 44 if (isFunction(x)) { 45 const f: Function = x; 46 const t: T = x; 47 } 48} 49 50function f11(x: string | (() => string) | undefined) { 51 if (isFunction(x)) { 52 x(); 53 } 54} 55 56function f12(x: string | (() => string) | undefined) { 57 const f = getFunction(x); // () => string 58 f(); 59} 60 61type Foo = { foo: string }; 62type Bar = { bar: string }; 63 64declare function fooBar(x: { foo: string, bar: string }): void; 65declare function fooBat(x: { foo: string, bat: string }): void; 66 67type Extract2<T, U, V> = T extends U ? T extends V ? T : never : never; 68 69function f20<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: Extract2<T, Foo, Bar>) { 70 fooBar(x); 71 fooBar(y); 72 fooBar(z); 73} 74 75function f21<T>(x: Extract<Extract<T, Foo>, Bar>, y: Extract<T, Foo & Bar>, z: Extract2<T, Foo, Bar>) { 76 fooBat(x); // Error 77 fooBat(y); // Error 78 fooBat(z); // Error 79} 80 81// Repros from #22860 82 83class Opt<T> { 84 toVector(): Vector<T> { 85 return <any>undefined; 86 } 87} 88 89interface Seq<T> { 90 tail(): Opt<Seq<T>>; 91} 92 93class Vector<T> implements Seq<T> { 94 tail(): Opt<Vector<T>> { 95 return <any>undefined; 96 } 97 partition2<U extends T>(predicate:(v:T)=>v is U): [Vector<U>,Vector<Exclude<T, U>>]; 98 partition2(predicate:(x:T)=>boolean): [Vector<T>,Vector<T>]; 99 partition2<U extends T>(predicate:(v:T)=>boolean): [Vector<U>,Vector<any>] { 100 return <any>undefined; 101 } 102} 103 104interface A1<T> { 105 bat: B1<A1<T>>; 106} 107 108interface B1<T> extends A1<T> { 109 bat: B1<B1<T>>; 110 boom: T extends any ? true : true 111} 112 113// Repro from #22899 114 115declare function toString1(value: object | Function): string ; 116declare function toString2(value: Function): string ; 117 118function foo<T>(value: T) { 119 if (isFunction(value)) { 120 toString1(value); 121 toString2(value); 122 } 123} 124 125// Repro from #23052 126 127type A<T, V, E> = 128 T extends object 129 ? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: A<T[Q], V, E>; } 130 : T extends V ? T : never; 131 132type B<T, V> = 133 T extends object 134 ? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: B<T[Q], V>; } 135 : T extends V ? T : never; 136 137type C<T, V, E> = 138 { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: C<T[Q], V, E>; }; 139 140// Repro from #23100 141 142type A2<T, V, E> = 143 T extends object ? T extends any[] ? T : { [Q in keyof T]: A2<T[Q], V, E>; } : T; 144 145type B2<T, V> = 146 T extends object ? T extends any[] ? T : { [Q in keyof T]: B2<T[Q], V>; } : T; 147 148type C2<T, V, E> = 149 T extends object ? { [Q in keyof T]: C2<T[Q], V, E>; } : T; 150 151// Repro from #28654 152 153type MaybeTrue<T extends { b: boolean }> = true extends T["b"] ? "yes" : "no"; 154 155type T0 = MaybeTrue<{ b: never }> // "no" 156type T1 = MaybeTrue<{ b: false }>; // "no" 157type T2 = MaybeTrue<{ b: true }>; // "yes" 158type T3 = MaybeTrue<{ b: boolean }>; // "yes" 159 160// Repro from #28824 161 162type Union = 'a' | 'b'; 163type Product<A extends Union, B> = { f1: A, f2: B}; 164type ProductUnion = Product<'a', 0> | Product<'b', 1>; 165 166// {a: "b"; b: "a"} 167type UnionComplement = { 168 [K in Union]: Exclude<Union, K> 169}; 170type UCA = UnionComplement['a']; 171type UCB = UnionComplement['b']; 172 173// {a: "a"; b: "b"} 174type UnionComplementComplement = { 175 [K in Union]: Exclude<Union, Exclude<Union, K>> 176}; 177type UCCA = UnionComplementComplement['a']; 178type UCCB = UnionComplementComplement['b']; 179 180// {a: Product<'b', 1>; b: Product<'a', 0>} 181type ProductComplement = { 182 [K in Union]: Exclude<ProductUnion, { f1: K }> 183}; 184type PCA = ProductComplement['a']; 185type PCB = ProductComplement['b']; 186 187// {a: Product<'a', 0>; b: Product<'b', 1>} 188type ProductComplementComplement = { 189 [K in Union]: Exclude<ProductUnion, Exclude<ProductUnion, { f1: K }>> 190}; 191type PCCA = ProductComplementComplement['a']; 192type PCCB = ProductComplementComplement['b']; 193 194// Repro from #31326 195 196type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never; 197type What = Hmm<{}, { a: string }> 198const w: What = { a: 4 }; 199 200// Repro from #33568 201 202declare function save(_response: IRootResponse<string>): void; 203 204exportCommand(save); 205 206declare function exportCommand<TResponse>(functionToCall: IExportCallback<TResponse>): void; 207 208interface IExportCallback<TResponse> { 209 (response: IRootResponse<TResponse>): void; 210} 211 212type IRootResponse<TResponse> = 213 TResponse extends IRecord ? IRecordResponse<TResponse> : IResponse<TResponse>; 214 215interface IRecord { 216 readonly Id: string; 217} 218 219declare type IRecordResponse<T extends IRecord> = IResponse<T> & { 220 sendRecord(): void; 221}; 222 223declare type IResponse<T> = { 224 sendValue(name: keyof GetAllPropertiesOfType<T, string>): void; 225}; 226 227declare type GetPropertyNamesOfType<T, RestrictToType> = { 228 [PropertyName in Extract<keyof T, string>]: T[PropertyName] extends RestrictToType ? PropertyName : never 229}[Extract<keyof T, string>]; 230 231declare type GetAllPropertiesOfType<T, RestrictToType> = Pick< 232 T, 233 GetPropertyNamesOfType<Required<T>, RestrictToType> 234>; 235 236// Repro from #33568 237 238declare function ff(x: Foo3<string>): void; 239declare function gg<T>(f: (x: Foo3<T>) => void): void; 240type Foo3<T> = T extends number ? { n: T } : { x: T }; 241gg(ff); 242 243// Repro from #41613 244 245type Wat<K extends string> = { x: { y: 0, z: 1 } } extends { x: { [P in K]: 0 } } ? true : false; 246 247type Huh = Wat<"y">; // true 248