• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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