Skip to content

Commit 1e45293

Browse files
committed
Add test showing use case for jest's 'each'
1 parent 70fdb52 commit 1e45293

File tree

5 files changed

+327
-2
lines changed

5 files changed

+327
-2
lines changed

src/compiler/checker.ts

+4
Original file line numberDiff line numberDiff line change
@@ -21195,6 +21195,10 @@ namespace ts {
2119521195
let arrayOrTupleConstituent: TypeReference | undefined;
2119621196
for (const constituent of (type as IntersectionType).types) {
2119721197
if (isArrayOrTupleType(constituent)) {
21198+
// If this is an intersection of two array or tuple types, prefer neither.
21199+
if (arrayOrTupleConstituent) {
21200+
return undefined;
21201+
}
2119821202
arrayOrTupleConstituent = constituent;
2119921203
}
2120021204
else {

tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols

+187
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,190 @@ const raw_r2 = raw`a\n${"b"}
158158

159159
c`;
160160

161+
// Jest's `it.each`:
162+
type Whitespace = " " | "\t" | "\v"
163+
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
164+
165+
type Trim<S extends string, Chars extends string = Whitespace | "\n"> =
166+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
167+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
168+
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
169+
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
170+
171+
S extends `${Chars}${infer R}` ? Trim<R, Chars> :
172+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
173+
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
174+
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 47, 30))
175+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
176+
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 47, 30))
177+
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
178+
179+
S extends `${infer R}${Chars}` ? Trim<R, Chars> :
180+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
181+
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 48, 22))
182+
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
183+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
184+
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 48, 22))
185+
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
186+
187+
S;
188+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
189+
190+
type Split<S extends string, D extends string> =
191+
>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6))
192+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
193+
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
194+
195+
S extends D ? [] :
196+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
197+
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
198+
199+
S extends `${infer H}${D}${infer T}` ? [H, ...Split<T, D>] :
200+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
201+
>H : Symbol(H, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 22))
202+
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
203+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 36))
204+
>H : Symbol(H, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 22))
205+
>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6))
206+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 36))
207+
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
208+
209+
[S];
210+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
211+
212+
type ParseRows<A extends any[], S extends readonly string[], Row extends any[] = [], Rows extends any[][] = []> =
213+
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
214+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15))
215+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31))
216+
>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60))
217+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
218+
219+
[A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ?
220+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15))
221+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31))
222+
>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26))
223+
>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39))
224+
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60))
225+
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88))
226+
227+
Trim<TH, Whitespace> extends "|" ? ParseRows<AT, TT, [...Row, AH], Rows> :
228+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
229+
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60))
230+
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
231+
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
232+
>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39))
233+
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88))
234+
>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60))
235+
>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26))
236+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
237+
238+
Trim<TH, Whitespace> extends "\n" | "" ? ParseRows<AT, TT, [], [...Rows, [...Row, AH]]> :
239+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
240+
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60))
241+
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
242+
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
243+
>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39))
244+
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88))
245+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
246+
>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60))
247+
>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26))
248+
249+
never :
250+
[A, S] extends [[], readonly []] ? Rows :
251+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15))
252+
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31))
253+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
254+
255+
never;
256+
257+
type JestEachArgument<Headers extends string[], Rows extends any[][]> = {
258+
>JestEachArgument : Symbol(JestEachArgument, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 62, 10))
259+
>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22))
260+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
261+
262+
[P1 in keyof Rows]: {
263+
>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5))
264+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
265+
266+
[P2 in keyof Headers as P2 extends `${number}` ? Trim<Headers[P2]> : never]:
267+
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
268+
>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22))
269+
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
270+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
271+
>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22))
272+
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
273+
274+
P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined;
275+
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
276+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
277+
>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5))
278+
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
279+
>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5))
280+
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
281+
282+
};
283+
}[number];
284+
285+
type JestEachFunction<Arg> = (name: string, cb: (arg: Arg) => void, timeout?: number) => void;
286+
>JestEachFunction : Symbol(JestEachFunction, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 69, 10))
287+
>Arg : Symbol(Arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 22))
288+
>name : Symbol(name, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 30))
289+
>cb : Symbol(cb, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 43))
290+
>arg : Symbol(arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 49))
291+
>Arg : Symbol(Arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 22))
292+
>timeout : Symbol(timeout, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 67))
293+
294+
type JestEach<T extends readonly string[], A extends any[]> =
295+
>JestEach : Symbol(JestEach, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 94))
296+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 14))
297+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 42))
298+
299+
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
300+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 14))
301+
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 29))
302+
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 57))
303+
304+
JestEachFunction<JestEachArgument<Split<Trim<TH>, "|">, ParseRows<A, TT>>> :
305+
>JestEachFunction : Symbol(JestEachFunction, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 69, 10))
306+
>JestEachArgument : Symbol(JestEachArgument, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 62, 10))
307+
>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6))
308+
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
309+
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 29))
310+
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
311+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 42))
312+
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 57))
313+
314+
null;
315+
316+
declare function each<T extends readonly string[], A extends unknown[]>(strs: T, ...args: A): JestEach<T, A>;
317+
>each : Symbol(each, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 76, 13))
318+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22))
319+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50))
320+
>strs : Symbol(strs, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 72))
321+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22))
322+
>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 80))
323+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50))
324+
>JestEach : Symbol(JestEach, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 94))
325+
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22))
326+
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50))
327+
328+
each`
329+
>each : Symbol(each, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 76, 13))
330+
331+
foo | bar
332+
${"a"} | ${1}
333+
${"c"} | ${undefined}
334+
>undefined : Symbol(undefined)
335+
336+
`("test", ({ foo, bar }) => {
337+
>foo : Symbol(foo, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 12))
338+
>bar : Symbol(bar, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 17))
339+
340+
foo;
341+
>foo : Symbol(foo, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 12))
342+
343+
bar;
344+
>bar : Symbol(bar, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 17))
345+
346+
});
347+

tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types

+87-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf<readonly ["a", "c"], read
6969

7070
// interpolation example
7171
type TemplatePrimitive = string | number | bigint | boolean | null | undefined;
72-
>TemplatePrimitive : string | number | bigint | boolean
72+
>TemplatePrimitive : string | number | bigint | boolean | null | undefined
7373
>null : null
7474

7575
type Interpolate<T extends readonly string[], A extends any[], R extends string = ''> =
@@ -141,3 +141,89 @@ const raw_r2 = raw`a\n${"b"}
141141

142142
c`;
143143

144+
// Jest's `it.each`:
145+
type Whitespace = " " | "\t" | "\v"
146+
>Whitespace : " " | "\t" | "\v"
147+
148+
type Trim<S extends string, Chars extends string = Whitespace | "\n"> =
149+
>Trim : Trim<S, Chars>
150+
151+
S extends `${Chars}${infer R}` ? Trim<R, Chars> :
152+
S extends `${infer R}${Chars}` ? Trim<R, Chars> :
153+
S;
154+
155+
type Split<S extends string, D extends string> =
156+
>Split : Split<S, D>
157+
158+
S extends D ? [] :
159+
S extends `${infer H}${D}${infer T}` ? [H, ...Split<T, D>] :
160+
[S];
161+
162+
type ParseRows<A extends any[], S extends readonly string[], Row extends any[] = [], Rows extends any[][] = []> =
163+
>ParseRows : ParseRows<A, S, Row, Rows>
164+
165+
[A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ?
166+
Trim<TH, Whitespace> extends "|" ? ParseRows<AT, TT, [...Row, AH], Rows> :
167+
Trim<TH, Whitespace> extends "\n" | "" ? ParseRows<AT, TT, [], [...Rows, [...Row, AH]]> :
168+
never :
169+
[A, S] extends [[], readonly []] ? Rows :
170+
never;
171+
172+
type JestEachArgument<Headers extends string[], Rows extends any[][]> = {
173+
>JestEachArgument : JestEachArgument<Headers, Rows>
174+
175+
[P1 in keyof Rows]: {
176+
[P2 in keyof Headers as P2 extends `${number}` ? Trim<Headers[P2]> : never]:
177+
P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined;
178+
};
179+
}[number];
180+
181+
type JestEachFunction<Arg> = (name: string, cb: (arg: Arg) => void, timeout?: number) => void;
182+
>JestEachFunction : JestEachFunction<Arg>
183+
>name : string
184+
>cb : (arg: Arg) => void
185+
>arg : Arg
186+
>timeout : number | undefined
187+
188+
type JestEach<T extends readonly string[], A extends any[]> =
189+
>JestEach : JestEach<T, A>
190+
191+
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
192+
JestEachFunction<JestEachArgument<Split<Trim<TH>, "|">, ParseRows<A, TT>>> :
193+
null;
194+
>null : null
195+
196+
declare function each<T extends readonly string[], A extends unknown[]>(strs: T, ...args: A): JestEach<T, A>;
197+
>each : <T extends readonly string[], A extends unknown[]>(strs: T, ...args: A) => JestEach<T, A>
198+
>strs : T
199+
>args : A
200+
201+
each`
202+
>each` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}`("test", ({ foo, bar }) => { foo; bar;}) : void
203+
>each` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}` : JestEachFunction<{ foo: string; bar: number; } | { foo: string; bar: undefined; }>
204+
>each : <T extends readonly string[], A extends unknown[]>(strs: T, ...args: A) => JestEach<T, A>
205+
>` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}` : string
206+
207+
foo | bar
208+
${"a"} | ${1}
209+
>"a" : "a"
210+
>1 : 1
211+
212+
${"c"} | ${undefined}
213+
>"c" : "c"
214+
>undefined : undefined
215+
216+
`("test", ({ foo, bar }) => {
217+
>"test" : "test"
218+
>({ foo, bar }) => { foo; bar;} : ({ foo, bar }: { foo: string; bar: number; } | { foo: string; bar: undefined; }) => void
219+
>foo : string
220+
>bar : number | undefined
221+
222+
foo;
223+
>foo : string
224+
225+
bar;
226+
>bar : number | undefined
227+
228+
});
229+

tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts

+47
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// @target: esnext
22
// @noEmit: true
3+
// @strict: true
34

45
// overload resolution
56
declare function f1(array: TemplateStringsArrayOf<readonly ["a", ...string[]]>, ...args: any): "A";
@@ -43,3 +44,49 @@ const raw_r1 = raw`a${1}c`; // "a1c"
4344
// "a\\nb\nc"
4445
const raw_r2 = raw`a\n${"b"}
4546
c`;
47+
48+
// Jest's `it.each`:
49+
type Whitespace = " " | "\t" | "\v"
50+
51+
type Trim<S extends string, Chars extends string = Whitespace | "\n"> =
52+
S extends `${Chars}${infer R}` ? Trim<R, Chars> :
53+
S extends `${infer R}${Chars}` ? Trim<R, Chars> :
54+
S;
55+
56+
type Split<S extends string, D extends string> =
57+
S extends D ? [] :
58+
S extends `${infer H}${D}${infer T}` ? [H, ...Split<T, D>] :
59+
[S];
60+
61+
type ParseRows<A extends any[], S extends readonly string[], Row extends any[] = [], Rows extends any[][] = []> =
62+
[A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ?
63+
Trim<TH, Whitespace> extends "|" ? ParseRows<AT, TT, [...Row, AH], Rows> :
64+
Trim<TH, Whitespace> extends "\n" | "" ? ParseRows<AT, TT, [], [...Rows, [...Row, AH]]> :
65+
never :
66+
[A, S] extends [[], readonly []] ? Rows :
67+
never;
68+
69+
type JestEachArgument<Headers extends string[], Rows extends any[][]> = {
70+
[P1 in keyof Rows]: {
71+
[P2 in keyof Headers as P2 extends `${number}` ? Trim<Headers[P2]> : never]:
72+
P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined;
73+
};
74+
}[number];
75+
76+
type JestEachFunction<Arg> = (name: string, cb: (arg: Arg) => void, timeout?: number) => void;
77+
78+
type JestEach<T extends readonly string[], A extends any[]> =
79+
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
80+
JestEachFunction<JestEachArgument<Split<Trim<TH>, "|">, ParseRows<A, TT>>> :
81+
null;
82+
83+
declare function each<T extends readonly string[], A extends unknown[]>(strs: T, ...args: A): JestEach<T, A>;
84+
85+
each`
86+
foo | bar
87+
${"a"} | ${1}
88+
${"c"} | ${undefined}
89+
`("test", ({ foo, bar }) => {
90+
foo;
91+
bar;
92+
});

tests/cases/conformance/types/conditional/inferTypes1.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,5 @@ type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
190190

191191
// Infer from an intersected tuple
192192
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
193-
type T100 = Head<["a", "c"] & { foo: "bar" }>;
193+
type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a"
194+
type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c"

0 commit comments

Comments
 (0)