• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// @strict: true
2// @declaration: true
3
4type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">;  // "b" | "d"
5type T01 = Extract<"a" | "b" | "c" | "d", "a" | "c" | "f">;  // "a" | "c"
6
7type T02 = Exclude<string | number | (() => void), Function>;  // string | number
8type T03 = Extract<string | number | (() => void), Function>;  // () => void
9
10type T04 = NonNullable<string | number | undefined>;  // string | number
11type T05 = NonNullable<(() => string) | string[] | null | undefined>;  // (() => string) | string[]
12
13function f1<T>(x: T, y: NonNullable<T>) {
14    x = y;
15    y = x;  // Error
16}
17
18function f2<T extends string | undefined>(x: T, y: NonNullable<T>) {
19    x = y;
20    y = x;  // Error
21    let s1: string = x;  // Error
22    let s2: string = y;
23}
24
25function f3<T>(x: Partial<T>[keyof T], y: NonNullable<Partial<T>[keyof T]>) {
26    x = y;
27    y = x;  // Error
28}
29
30function f4<T extends { x: string | undefined }>(x: T["x"], y: NonNullable<T["x"]>) {
31    x = y;
32    y = x;  // Error
33    let s1: string = x;  // Error
34    let s2: string = y;
35}
36
37type Options = { k: "a", a: number } | { k: "b", b: string } | { k: "c", c: boolean };
38
39type T10 = Exclude<Options, { k: "a" | "b" }>;  // { k: "c", c: boolean }
40type T11 = Extract<Options, { k: "a" | "b" }>;  // { k: "a", a: number } | { k: "b", b: string }
41
42type T12 = Exclude<Options, { k: "a" } | { k: "b" }>;  // { k: "c", c: boolean }
43type T13 = Extract<Options, { k: "a" } | { k: "b" }>;  // { k: "a", a: number } | { k: "b", b: string }
44
45type T14 = Exclude<Options, { q: "a" }>;  // Options
46type T15 = Extract<Options, { q: "a" }>;  // never
47
48declare function f5<T extends Options, K extends string>(p: K): Extract<T, { k: K }>;
49let x0 = f5("a");  // { k: "a", a: number }
50
51type OptionsOfKind<K extends Options["k"]> = Extract<Options, { k: K }>;
52
53type T16 = OptionsOfKind<"a" | "b">;  // { k: "a", a: number } | { k: "b", b: string }
54
55type Select<T, K extends keyof T, V extends T[K]> = Extract<T, { [P in K]: V }>;
56
57type T17 = Select<Options, "k", "a" | "b">;  // // { k: "a", a: number } | { k: "b", b: string }
58
59type TypeName<T> =
60    T extends string ? "string" :
61    T extends number ? "number" :
62    T extends boolean ? "boolean" :
63    T extends undefined ? "undefined" :
64    T extends Function ? "function" :
65    "object";
66
67type T20 = TypeName<string | (() => void)>;  // "string" | "function"
68type T21 = TypeName<any>;  // "string" | "number" | "boolean" | "undefined" | "function" | "object"
69type T22 = TypeName<never>;  // never
70type T23 = TypeName<{}>;  // "object"
71
72type KnockoutObservable<T> = { object: T };
73type KnockoutObservableArray<T> = { array: T };
74
75type KnockedOut<T> = T extends any[] ? KnockoutObservableArray<T[number]> : KnockoutObservable<T>;
76
77type KnockedOutObj<T> = {
78    [P in keyof T]: KnockedOut<T[P]>;
79}
80
81interface Item {
82    id: number;
83    name: string;
84    subitems: string[];
85}
86
87type KOItem = KnockedOutObj<Item>;
88
89interface Part {
90    id: number;
91    name: string;
92    subparts: Part[];
93    updatePart(newName: string): void;
94}
95
96type FunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T];
97type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>;
98
99type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];
100type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
101
102type T30 = FunctionProperties<Part>;
103type T31 = NonFunctionProperties<Part>;
104
105function f7<T>(x: T, y: FunctionProperties<T>, z: NonFunctionProperties<T>) {
106    x = y;  // Error
107    x = z;  // Error
108    y = x;
109    y = z;  // Error
110    z = x;
111    z = y;  // Error
112}
113
114function f8<T>(x: keyof T, y: FunctionPropertyNames<T>, z: NonFunctionPropertyNames<T>) {
115    x = y;
116    x = z;
117    y = x;  // Error
118    y = z;  // Error
119    z = x;  // Error
120    z = y;  // Error
121}
122
123type DeepReadonly<T> =
124    T extends any[] ? DeepReadonlyArray<T[number]> :
125    T extends object ? DeepReadonlyObject<T> :
126    T;
127
128interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
129
130type DeepReadonlyObject<T> = {
131    readonly [P in NonFunctionPropertyNames<T>]: DeepReadonly<T[P]>;
132};
133
134function f10(part: DeepReadonly<Part>) {
135    let name: string = part.name;
136    let id: number = part.subparts[0].id;
137    part.id = part.id;  // Error
138    part.subparts[0] = part.subparts[0];  // Error
139    part.subparts[0].id = part.subparts[0].id;  // Error
140    part.updatePart("hello");  // Error
141}
142
143type ZeroOf<T extends number | string | boolean> = T extends number ? 0 : T extends string ? "" : false;
144
145function zeroOf<T extends number | string | boolean>(value: T) {
146    return <ZeroOf<T>>(typeof value === "number" ? 0 : typeof value === "string" ? "" : false);
147}
148
149function f20<T extends string>(n: number, b: boolean, x: number | boolean, y: T) {
150    zeroOf(5);  // 0
151    zeroOf("hello");  // ""
152    zeroOf(true);  // false
153    zeroOf(n);  // 0
154    zeroOf(b);  // False
155    zeroOf(x);  // 0 | false
156    zeroOf(y);  // ZeroOf<T>
157}
158
159function f21<T extends number | string>(x: T, y: ZeroOf<T>) {
160    let z1: number | string = y;
161    let z2: 0 | "" = y;
162    x = y;  // Error
163    y = x;  // Error
164}
165
166type T35<T extends { a: string, b: number }> = T[];
167type T36<T> = T extends { a: string } ? T extends { b: number } ? T35<T> : never : never;
168type T37<T> = T extends { b: number } ? T extends { a: string } ? T35<T> : never : never;
169type T38<T> = [T] extends [{ a: string }] ? [T] extends [{ b: number }] ? T35<T> : never : never;
170
171type Extends<T, U> = T extends U ? true : false;
172type If<C extends boolean, T, F> = C extends true ? T : F;
173type Not<C extends boolean> = If<C, false, true>;
174type And<A extends boolean, B extends boolean> = If<A, B, false>;
175type Or<A extends boolean, B extends boolean> = If<A, true, B>;
176
177type IsString<T> = Extends<T, string>;
178
179type Q1 = IsString<number>;  // false
180type Q2 = IsString<"abc">;  // true
181type Q3 = IsString<any>;  // boolean
182type Q4 = IsString<never>;  // never
183
184type N1 = Not<false>;  // true
185type N2 = Not<true>;  // false
186type N3 = Not<boolean>;  // boolean
187
188type A1 = And<false, false>;  // false
189type A2 = And<false, true>;  // false
190type A3 = And<true, false>;  // false
191type A4 = And<true, true>;  // true
192type A5 = And<boolean, false>;  // false
193type A6 = And<false, boolean>;  // false
194type A7 = And<boolean, true>;  // boolean
195type A8 = And<true, boolean>;  // boolean
196type A9 = And<boolean, boolean>;  // boolean
197
198type O1 = Or<false, false>;  // false
199type O2 = Or<false, true>;  // true
200type O3 = Or<true, false>;  // true
201type O4 = Or<true, true>;  // true
202type O5 = Or<boolean, false>;  // boolean
203type O6 = Or<false, boolean>;  // boolean
204type O7 = Or<boolean, true>;  // true
205type O8 = Or<true, boolean>;  // true
206type O9 = Or<boolean, boolean>;  // boolean
207
208type T40 = never extends never ? true : false;  // true
209type T41 = number extends never ? true : false;  // false
210type T42 = never extends number ? true : false;  // true
211
212type IsNever<T> = [T] extends [never] ? true : false;
213
214type T50 = IsNever<never>;  // true
215type T51 = IsNever<number>;  // false
216type T52 = IsNever<any>;  // false
217
218function f22<T>(x: T extends (infer U)[] ? U[] : never) {
219    let e = x[0];  // {}
220}
221
222function f23<T extends string[]>(x: T extends (infer U)[] ? U[] : never) {
223    let e = x[0];  // string
224}
225
226// Repros from #21664
227
228type Eq<T, U> = T extends U ? U extends T ? true : false : false;
229type T60 = Eq<true, true>;  // true
230type T61 = Eq<true, false>;  // false
231type T62 = Eq<false, true>;  // false
232type T63 = Eq<false, false>;  // true
233
234type Eq1<T, U> = Eq<T, U> extends false ? false : true;
235type T70 = Eq1<true, true>;  // true
236type T71 = Eq1<true, false>;  // false
237type T72 = Eq1<false, true>;  // false
238type T73 = Eq1<false, false>;  // true
239
240type Eq2<T, U> = Eq<T, U> extends true ? true : false;
241type T80 = Eq2<true, true>;  // true
242type T81 = Eq2<true, false>;  // false
243type T82 = Eq2<false, true>;  // false
244type T83 = Eq2<false, false>;  // true
245
246// Repro from #21756
247
248type Foo<T> = T extends string ? boolean : number;
249type Bar<T> = T extends string ? boolean : number;
250const convert = <U>(value: Foo<U>): Bar<U> => value;
251
252type Baz<T> = Foo<T>;
253const convert2 = <T>(value: Foo<T>): Baz<T> => value;
254
255function f31<T>() {
256    type T1 = T extends string ? boolean : number;
257    type T2 = T extends string ? boolean : number;
258    var x: T1;
259    var x: T2;
260}
261
262function f32<T, U>() {
263    type T1 = T & U extends string ? boolean : number;
264    type T2 = Foo<T & U>;
265    var z: T1;
266    var z: T2;  // Error, T2 is distributive, T1 isn't
267}
268
269function f33<T, U>() {
270    type T1 = Foo<T & U>;
271    type T2 = Bar<T & U>;
272    var z: T1;
273    var z: T2;
274}
275
276// Repro from #21823
277
278type T90<T> = T extends 0 ? 0 : () => 0;
279type T91<T> = T extends 0 ? 0 : () => 0;
280const f40 = <U>(a: T90<U>): T91<U> => a;
281const f41 = <U>(a: T91<U>): T90<U> => a;
282
283type T92<T> = T extends () => 0 ? () => 1 : () => 2;
284type T93<T> = T extends () => 0 ? () => 1 : () => 2;
285const f42 = <U>(a: T92<U>): T93<U> => a;
286const f43 = <U>(a: T93<U>): T92<U> => a;
287
288type T94<T> = T extends string ? true : 42;
289type T95<T> = T extends string ? boolean : number;
290const f44 = <U>(value: T94<U>): T95<U> => value;
291const f45 = <U>(value: T95<U>): T94<U> => value;  // Error
292
293// Repro from #21863
294
295function f50() {
296    type Eq<T, U> = T extends U ? U extends T ? true : false : false;
297    type If<S, T, U> = S extends false ? U : T;
298    type Omit<T extends object> = { [P in keyof T]: If<Eq<T[P], never>, never, P>; }[keyof T];
299    type Omit2<T extends object, U = never> = { [P in keyof T]: If<Eq<T[P], U>, never, P>; }[keyof T];
300    type A = Omit<{ a: void; b: never; }>;  // 'a'
301    type B = Omit2<{ a: void; b: never; }>;  // 'a'
302}
303
304// Repro from #21862
305
306type OldDiff<T extends keyof any, U extends keyof any> = (
307    & { [P in T]: P; }
308    & { [P in U]: never; }
309    & { [x: string]: never; }
310)[T];
311type NewDiff<T, U> = T extends U ? never : T;
312interface A {
313    a: 'a';
314}
315interface B1 extends A {
316    b: 'b';
317    c: OldDiff<keyof this, keyof A>;
318}
319interface B2 extends A {
320    b: 'b';
321    c: NewDiff<keyof this, keyof A>;
322}
323type c1 = B1['c']; // 'c' | 'b'
324type c2 = B2['c']; // 'c' | 'b'
325
326// Repro from #21929
327
328type NonFooKeys1<T extends object> = OldDiff<keyof T, 'foo'>;
329type NonFooKeys2<T extends object> = Exclude<keyof T, 'foo'>;
330
331type Test1 = NonFooKeys1<{foo: 1, bar: 2, baz: 3}>;  // "bar" | "baz"
332type Test2 = NonFooKeys2<{foo: 1, bar: 2, baz: 3}>;  // "bar" | "baz"
333
334// Repro from #21729
335
336interface Foo2 { foo: string; }
337interface Bar2 { bar: string; }
338type FooBar = Foo2 | Bar2;
339declare interface ExtractFooBar<FB extends FooBar> { }
340
341type Extracted<Struct> = {
342    [K in keyof Struct]: Struct[K] extends FooBar ? ExtractFooBar<Struct[K]> : Struct[K];
343}
344
345// Repro from #22985
346
347type RecursivePartial<T> = {
348  [P in keyof T]?: T[P] extends Array<any> ? {[index: number]: RecursivePartial<T[P][0]>} :
349    T[P] extends object ? RecursivePartial<T[P]> : T[P];
350};
351
352declare function assign<T>(o: T, a: RecursivePartial<T>): void;
353
354var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]}
355assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}})
356
357// Repros from #23843
358
359type Weird1 = (<U extends boolean>(a: U) => never) extends
360    (<U extends true>(a: U) => never) ? never : never;
361
362type Weird2 = (<U extends boolean>(a: U) => U) extends
363    (<U extends true>(a: U) => infer T) ? T : never;
364