mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Remove order dependence and add test showing use case for Jest's 'each'
This commit is contained in:
@@ -21195,6 +21195,10 @@ namespace ts {
|
||||
let arrayOrTupleConstituent: TypeReference | undefined;
|
||||
for (const constituent of (type as IntersectionType).types) {
|
||||
if (isArrayOrTupleType(constituent)) {
|
||||
// If this is an intersection of two array or tuple types, prefer neither.
|
||||
if (arrayOrTupleConstituent) {
|
||||
return undefined;
|
||||
}
|
||||
arrayOrTupleConstituent = constituent;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -246,5 +246,6 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322:
|
||||
|
||||
// Infer from an intersected tuple
|
||||
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a"
|
||||
type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c"
|
||||
|
||||
@@ -188,7 +188,8 @@ type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
|
||||
|
||||
// Infer from an intersected tuple
|
||||
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a"
|
||||
type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c"
|
||||
|
||||
|
||||
//// [inferTypes1.js]
|
||||
|
||||
@@ -784,8 +784,12 @@ type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : ne
|
||||
>_ : Symbol(_, Decl(inferTypes1.ts, 188, 64))
|
||||
>THead : Symbol(THead, Decl(inferTypes1.ts, 188, 48))
|
||||
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a"
|
||||
>T100 : Symbol(T100, Decl(inferTypes1.ts, 188, 84))
|
||||
>Head : Symbol(Head, Decl(inferTypes1.ts, 185, 64))
|
||||
>foo : Symbol(foo, Decl(inferTypes1.ts, 189, 31))
|
||||
|
||||
type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c"
|
||||
>T101 : Symbol(T101, Decl(inferTypes1.ts, 189, 46))
|
||||
>Head : Symbol(Head, Decl(inferTypes1.ts, 185, 64))
|
||||
|
||||
|
||||
@@ -497,7 +497,10 @@ type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
|
||||
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
|
||||
>Head : Head<T>
|
||||
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a"
|
||||
>T100 : "a"
|
||||
>foo : "bar"
|
||||
|
||||
type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c"
|
||||
>T101 : "a" | "c"
|
||||
|
||||
|
||||
@@ -158,3 +158,190 @@ const raw_r2 = raw`a\n${"b"}
|
||||
|
||||
c`;
|
||||
|
||||
// Jest's `it.each`:
|
||||
type Whitespace = " " | "\t" | "\v"
|
||||
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
|
||||
|
||||
type Trim<S extends string, Chars extends string = Whitespace | "\n"> =
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
|
||||
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
|
||||
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
|
||||
|
||||
S extends `${Chars}${infer R}` ? Trim<R, Chars> :
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
|
||||
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
|
||||
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 47, 30))
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 47, 30))
|
||||
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
|
||||
|
||||
S extends `${infer R}${Chars}` ? Trim<R, Chars> :
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
|
||||
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 48, 22))
|
||||
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>R : Symbol(R, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 48, 22))
|
||||
>Chars : Symbol(Chars, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 27))
|
||||
|
||||
S;
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 46, 10))
|
||||
|
||||
type Split<S extends string, D extends string> =
|
||||
>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6))
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
|
||||
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
|
||||
|
||||
S extends D ? [] :
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
|
||||
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
|
||||
|
||||
S extends `${infer H}${D}${infer T}` ? [H, ...Split<T, D>] :
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
|
||||
>H : Symbol(H, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 22))
|
||||
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 36))
|
||||
>H : Symbol(H, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 22))
|
||||
>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6))
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 53, 36))
|
||||
>D : Symbol(D, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 28))
|
||||
|
||||
[S];
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 51, 11))
|
||||
|
||||
type ParseRows<A extends any[], S extends readonly string[], Row extends any[] = [], Rows extends any[][] = []> =
|
||||
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15))
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31))
|
||||
>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
|
||||
|
||||
[A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ?
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15))
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31))
|
||||
>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26))
|
||||
>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39))
|
||||
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60))
|
||||
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88))
|
||||
|
||||
Trim<TH, Whitespace> extends "|" ? ParseRows<AT, TT, [...Row, AH], Rows> :
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60))
|
||||
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
|
||||
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
|
||||
>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39))
|
||||
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88))
|
||||
>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60))
|
||||
>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
|
||||
|
||||
Trim<TH, Whitespace> extends "\n" | "" ? ParseRows<AT, TT, [], [...Rows, [...Row, AH]]> :
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 60))
|
||||
>Whitespace : Symbol(Whitespace, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 41, 3))
|
||||
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
|
||||
>AT : Symbol(AT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 39))
|
||||
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 88))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
|
||||
>Row : Symbol(Row, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 60))
|
||||
>AH : Symbol(AH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 57, 26))
|
||||
|
||||
never :
|
||||
[A, S] extends [[], readonly []] ? Rows :
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 15))
|
||||
>S : Symbol(S, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 31))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 56, 84))
|
||||
|
||||
never;
|
||||
|
||||
type JestEachArgument<Headers extends string[], Rows extends any[][]> = {
|
||||
>JestEachArgument : Symbol(JestEachArgument, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 62, 10))
|
||||
>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
|
||||
|
||||
[P1 in keyof Rows]: {
|
||||
>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
|
||||
|
||||
[P2 in keyof Headers as P2 extends `${number}` ? Trim<Headers[P2]> : never]:
|
||||
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
|
||||
>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22))
|
||||
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>Headers : Symbol(Headers, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 22))
|
||||
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
|
||||
|
||||
P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined;
|
||||
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
|
||||
>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5))
|
||||
>Rows : Symbol(Rows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 64, 47))
|
||||
>P1 : Symbol(P1, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 65, 5))
|
||||
>P2 : Symbol(P2, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 66, 9))
|
||||
|
||||
};
|
||||
}[number];
|
||||
|
||||
type JestEachFunction<Arg> = (name: string, cb: (arg: Arg) => void, timeout?: number) => void;
|
||||
>JestEachFunction : Symbol(JestEachFunction, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 69, 10))
|
||||
>Arg : Symbol(Arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 22))
|
||||
>name : Symbol(name, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 30))
|
||||
>cb : Symbol(cb, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 43))
|
||||
>arg : Symbol(arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 49))
|
||||
>Arg : Symbol(Arg, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 22))
|
||||
>timeout : Symbol(timeout, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 67))
|
||||
|
||||
type JestEach<T extends readonly string[], A extends any[]> =
|
||||
>JestEach : Symbol(JestEach, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 94))
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 14))
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 42))
|
||||
|
||||
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 14))
|
||||
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 29))
|
||||
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 57))
|
||||
|
||||
JestEachFunction<JestEachArgument<Split<Trim<TH>, "|">, ParseRows<A, TT>>> :
|
||||
>JestEachFunction : Symbol(JestEachFunction, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 69, 10))
|
||||
>JestEachArgument : Symbol(JestEachArgument, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 62, 10))
|
||||
>Split : Symbol(Split, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 49, 6))
|
||||
>Trim : Symbol(Trim, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 44, 35))
|
||||
>TH : Symbol(TH, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 29))
|
||||
>ParseRows : Symbol(ParseRows, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 54, 8))
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 73, 42))
|
||||
>TT : Symbol(TT, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 74, 57))
|
||||
|
||||
null;
|
||||
|
||||
declare function each<T extends readonly string[], A extends unknown[]>(strs: T, ...args: A): JestEach<T, A>;
|
||||
>each : Symbol(each, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 76, 13))
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22))
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50))
|
||||
>strs : Symbol(strs, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 72))
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22))
|
||||
>args : Symbol(args, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 80))
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50))
|
||||
>JestEach : Symbol(JestEach, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 71, 94))
|
||||
>T : Symbol(T, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 22))
|
||||
>A : Symbol(A, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 78, 50))
|
||||
|
||||
each`
|
||||
>each : Symbol(each, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 76, 13))
|
||||
|
||||
foo | bar
|
||||
${"a"} | ${1}
|
||||
${"c"} | ${undefined}
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
`("test", ({ foo, bar }) => {
|
||||
>foo : Symbol(foo, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 12))
|
||||
>bar : Symbol(bar, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 17))
|
||||
|
||||
foo;
|
||||
>foo : Symbol(foo, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 12))
|
||||
|
||||
bar;
|
||||
>bar : Symbol(bar, Decl(taggedTemplateWithSpecificTemplateStrings.ts, 84, 17))
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOf<readonly ["a", "c"], read
|
||||
|
||||
// interpolation example
|
||||
type TemplatePrimitive = string | number | bigint | boolean | null | undefined;
|
||||
>TemplatePrimitive : string | number | bigint | boolean
|
||||
>TemplatePrimitive : string | number | bigint | boolean | null | undefined
|
||||
>null : null
|
||||
|
||||
type Interpolate<T extends readonly string[], A extends any[], R extends string = ''> =
|
||||
@@ -141,3 +141,89 @@ const raw_r2 = raw`a\n${"b"}
|
||||
|
||||
c`;
|
||||
|
||||
// Jest's `it.each`:
|
||||
type Whitespace = " " | "\t" | "\v"
|
||||
>Whitespace : " " | "\t" | "\v"
|
||||
|
||||
type Trim<S extends string, Chars extends string = Whitespace | "\n"> =
|
||||
>Trim : Trim<S, Chars>
|
||||
|
||||
S extends `${Chars}${infer R}` ? Trim<R, Chars> :
|
||||
S extends `${infer R}${Chars}` ? Trim<R, Chars> :
|
||||
S;
|
||||
|
||||
type Split<S extends string, D extends string> =
|
||||
>Split : Split<S, D>
|
||||
|
||||
S extends D ? [] :
|
||||
S extends `${infer H}${D}${infer T}` ? [H, ...Split<T, D>] :
|
||||
[S];
|
||||
|
||||
type ParseRows<A extends any[], S extends readonly string[], Row extends any[] = [], Rows extends any[][] = []> =
|
||||
>ParseRows : ParseRows<A, S, Row, Rows>
|
||||
|
||||
[A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ?
|
||||
Trim<TH, Whitespace> extends "|" ? ParseRows<AT, TT, [...Row, AH], Rows> :
|
||||
Trim<TH, Whitespace> extends "\n" | "" ? ParseRows<AT, TT, [], [...Rows, [...Row, AH]]> :
|
||||
never :
|
||||
[A, S] extends [[], readonly []] ? Rows :
|
||||
never;
|
||||
|
||||
type JestEachArgument<Headers extends string[], Rows extends any[][]> = {
|
||||
>JestEachArgument : JestEachArgument<Headers, Rows>
|
||||
|
||||
[P1 in keyof Rows]: {
|
||||
[P2 in keyof Headers as P2 extends `${number}` ? Trim<Headers[P2]> : never]:
|
||||
P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined;
|
||||
};
|
||||
}[number];
|
||||
|
||||
type JestEachFunction<Arg> = (name: string, cb: (arg: Arg) => void, timeout?: number) => void;
|
||||
>JestEachFunction : JestEachFunction<Arg>
|
||||
>name : string
|
||||
>cb : (arg: Arg) => void
|
||||
>arg : Arg
|
||||
>timeout : number | undefined
|
||||
|
||||
type JestEach<T extends readonly string[], A extends any[]> =
|
||||
>JestEach : JestEach<T, A>
|
||||
|
||||
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
|
||||
JestEachFunction<JestEachArgument<Split<Trim<TH>, "|">, ParseRows<A, TT>>> :
|
||||
null;
|
||||
>null : null
|
||||
|
||||
declare function each<T extends readonly string[], A extends unknown[]>(strs: T, ...args: A): JestEach<T, A>;
|
||||
>each : <T extends readonly string[], A extends unknown[]>(strs: T, ...args: A) => JestEach<T, A>
|
||||
>strs : T
|
||||
>args : A
|
||||
|
||||
each`
|
||||
>each` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}`("test", ({ foo, bar }) => { foo; bar;}) : void
|
||||
>each` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}` : JestEachFunction<{ foo: string; bar: number; } | { foo: string; bar: undefined; }>
|
||||
>each : <T extends readonly string[], A extends unknown[]>(strs: T, ...args: A) => JestEach<T, A>
|
||||
>` foo | bar ${"a"} | ${1} ${"c"} | ${undefined}` : string
|
||||
|
||||
foo | bar
|
||||
${"a"} | ${1}
|
||||
>"a" : "a"
|
||||
>1 : 1
|
||||
|
||||
${"c"} | ${undefined}
|
||||
>"c" : "c"
|
||||
>undefined : undefined
|
||||
|
||||
`("test", ({ foo, bar }) => {
|
||||
>"test" : "test"
|
||||
>({ foo, bar }) => { foo; bar;} : ({ foo, bar }: { foo: string; bar: number; } | { foo: string; bar: undefined; }) => void
|
||||
>foo : string
|
||||
>bar : number | undefined
|
||||
|
||||
foo;
|
||||
>foo : string
|
||||
|
||||
bar;
|
||||
>bar : number | undefined
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @target: esnext
|
||||
// @noEmit: true
|
||||
// @strict: true
|
||||
|
||||
// overload resolution
|
||||
declare function f1(array: TemplateStringsArrayOf<readonly ["a", ...string[]]>, ...args: any): "A";
|
||||
@@ -43,3 +44,49 @@ const raw_r1 = raw`a${1}c`; // "a1c"
|
||||
// "a\\nb\nc"
|
||||
const raw_r2 = raw`a\n${"b"}
|
||||
c`;
|
||||
|
||||
// Jest's `it.each`:
|
||||
type Whitespace = " " | "\t" | "\v"
|
||||
|
||||
type Trim<S extends string, Chars extends string = Whitespace | "\n"> =
|
||||
S extends `${Chars}${infer R}` ? Trim<R, Chars> :
|
||||
S extends `${infer R}${Chars}` ? Trim<R, Chars> :
|
||||
S;
|
||||
|
||||
type Split<S extends string, D extends string> =
|
||||
S extends D ? [] :
|
||||
S extends `${infer H}${D}${infer T}` ? [H, ...Split<T, D>] :
|
||||
[S];
|
||||
|
||||
type ParseRows<A extends any[], S extends readonly string[], Row extends any[] = [], Rows extends any[][] = []> =
|
||||
[A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ?
|
||||
Trim<TH, Whitespace> extends "|" ? ParseRows<AT, TT, [...Row, AH], Rows> :
|
||||
Trim<TH, Whitespace> extends "\n" | "" ? ParseRows<AT, TT, [], [...Rows, [...Row, AH]]> :
|
||||
never :
|
||||
[A, S] extends [[], readonly []] ? Rows :
|
||||
never;
|
||||
|
||||
type JestEachArgument<Headers extends string[], Rows extends any[][]> = {
|
||||
[P1 in keyof Rows]: {
|
||||
[P2 in keyof Headers as P2 extends `${number}` ? Trim<Headers[P2]> : never]:
|
||||
P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined;
|
||||
};
|
||||
}[number];
|
||||
|
||||
type JestEachFunction<Arg> = (name: string, cb: (arg: Arg) => void, timeout?: number) => void;
|
||||
|
||||
type JestEach<T extends readonly string[], A extends any[]> =
|
||||
T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ?
|
||||
JestEachFunction<JestEachArgument<Split<Trim<TH>, "|">, ParseRows<A, TT>>> :
|
||||
null;
|
||||
|
||||
declare function each<T extends readonly string[], A extends unknown[]>(strs: T, ...args: A): JestEach<T, A>;
|
||||
|
||||
each`
|
||||
foo | bar
|
||||
${"a"} | ${1}
|
||||
${"c"} | ${undefined}
|
||||
`("test", ({ foo, bar }) => {
|
||||
foo;
|
||||
bar;
|
||||
});
|
||||
|
||||
@@ -190,4 +190,5 @@ type Foo2<A extends any[]> = ReturnType<(...args: A) => string>;
|
||||
|
||||
// Infer from an intersected tuple
|
||||
type Head<T extends string[]> = T extends [infer THead, ...infer _] ? THead : never;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>;
|
||||
type T100 = Head<["a", "c"] & { foo: "bar" }>; // "a"
|
||||
type T101 = Head<["a", "c"] & readonly ["a", "c"]>; // "a" | "c"
|
||||
|
||||
Reference in New Issue
Block a user