• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// @strict: true
2// @declaration: true
3// @target: esnext
4
5// Awaiting promises
6
7type Awaited<T> =
8    T extends null | undefined ? T :
9    T extends PromiseLike<infer U> ? Awaited<U> :
10    T;
11
12type MyPromise<T> = {
13    then<U>(f: ((value: T) => U | PromiseLike<U>) | null | undefined): MyPromise<U>;
14}
15
16type InfinitePromise<T> = Promise<InfinitePromise<T>>;
17
18type P0 = Awaited<Promise<string | Promise<MyPromise<number> | null> | undefined>>;
19type P1 = Awaited<any>;
20type P2 = Awaited<InfinitePromise<number>>;  // Error
21
22function f11<T, U extends T>(tx: T, ta: Awaited<T>, ux: U, ua: Awaited<U>) {
23    ta = ua;
24    ua = ta;  // Error
25    ta = tx;  // Error
26    tx = ta;  // Error
27}
28
29// Flattening arrays
30
31type Flatten<T extends readonly unknown[]> = T extends unknown[] ? _Flatten<T>[] : readonly _Flatten<T>[];
32type _Flatten<T> = T extends readonly (infer U)[] ? _Flatten<U> : T;
33
34type InfiniteArray<T> = InfiniteArray<T>[];
35
36type B0 = Flatten<string[][][]>;
37type B1 = Flatten<string[][] | readonly (number[] | boolean[][])[]>;
38type B2 = Flatten<InfiniteArray<string>>;
39type B3 = B2[0];  // Error
40
41// Repeating tuples
42
43type TupleOf<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never;
44type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;
45
46type TT0 = TupleOf<string, 4>;
47type TT1 = TupleOf<number, 0 | 2 | 4>;
48type TT2 = TupleOf<number, number>;
49type TT3 = TupleOf<number, any>;
50type TT4 = TupleOf<number, 100>;  // Depth error
51
52function f22<N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) {
53    tn = tm;
54    tm = tn;
55}
56
57declare function f23<T>(t: TupleOf<T, 3>): T;
58
59f23(['a', 'b', 'c']);  // string
60
61// Inference to recursive type
62
63interface Box<T> { value: T };
64type RecBox<T> = T | Box<RecBox<T>>;
65type InfBox<T> = Box<InfBox<T>>;
66
67declare function unbox<T>(box: RecBox<T>): T
68
69type T1 = Box<string>;
70type T2 = Box<T1>;
71type T3 = Box<T2>;
72type T4 = Box<T3>;
73type T5 = Box<T4>;
74type T6 = Box<T5>;
75
76declare let b1: Box<Box<Box<Box<Box<Box<string>>>>>>;
77declare let b2: T6;
78declare let b3: InfBox<string>;
79declare let b4: { value: { value: { value: typeof b4 }}};
80
81unbox(b1);  // string
82unbox(b2);  // string
83unbox(b3);  // InfBox<string>
84unbox({ value: { value: { value: { value: { value: { value: 5 }}}}}});  // number
85unbox(b4);  // { value: { value: typeof b4 }}
86unbox({ value: { value: { get value() { return this; } }}});  // { readonly value: ... }
87
88// Inference from nested instantiations of same generic types
89
90type Box1<T> = { value: T };
91type Box2<T> = { value: T };
92
93declare function foo<T>(x: Box1<Box1<T>>): T;
94
95declare let z: Box2<Box2<string>>;
96
97foo(z);  // unknown, but ideally would be string (requires unique recursion ID for each type reference)
98
99// Intersect tuple element types
100
101type Intersect<U extends any[], R = unknown> = U extends [infer H, ...infer T] ? Intersect<T, R & H> : R;
102
103type QQ = Intersect<[string[], number[], 7]>;
104
105// Infer between structurally identical recursive conditional types
106
107type Unpack1<T> = T extends (infer U)[] ? Unpack1<U> : T;
108type Unpack2<T> = T extends (infer U)[] ? Unpack2<U> : T;
109
110function f20<T, U extends T>(x: Unpack1<T>, y: Unpack2<T>) {
111    x = y;
112    y = x;
113    f20(y, x);
114}
115
116type Grow1<T extends unknown[], N extends number> = T['length'] extends N ? T : Grow1<[number, ...T], N>;
117type Grow2<T extends unknown[], N extends number> = T['length'] extends N ? T : Grow2<[string, ...T], N>;
118
119function f21<T extends number>(x: Grow1<[], T>, y: Grow2<[], T>) {
120    f21(y, x);  // Error
121}
122
123// Repros from #41756
124
125type ParseSuccess<R extends string> = { rest: R };
126
127type ParseManyWhitespace<S extends string> =
128    S extends ` ${infer R0}` ?
129        ParseManyWhitespace<R0> extends ParseSuccess<infer R1> ? ParseSuccess<R1> : null :
130        ParseSuccess<S>;
131
132type TP1 = ParseManyWhitespace<" foo">;
133
134type ParseManyWhitespace2<S extends string> =
135    S extends ` ${infer R0}` ?
136        Helper<ParseManyWhitespace2<R0>> :
137        ParseSuccess<S>;
138
139type Helper<T> = T extends ParseSuccess<infer R> ? ParseSuccess<R> : null
140
141type TP2 = ParseManyWhitespace2<" foo">;
142