diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6f190bf74c6..973d4271e25 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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 { diff --git a/tests/baselines/reference/inferTypes1.errors.txt b/tests/baselines/reference/inferTypes1.errors.txt index 542ded65d43..cec8eaea55c 100644 --- a/tests/baselines/reference/inferTypes1.errors.txt +++ b/tests/baselines/reference/inferTypes1.errors.txt @@ -246,5 +246,6 @@ tests/cases/conformance/types/conditional/inferTypes1.ts(153,40): error TS2322: // Infer from an intersected tuple type Head = 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" \ No newline at end of file diff --git a/tests/baselines/reference/inferTypes1.js b/tests/baselines/reference/inferTypes1.js index b431288fb20..67ab98f9b31 100644 --- a/tests/baselines/reference/inferTypes1.js +++ b/tests/baselines/reference/inferTypes1.js @@ -188,7 +188,8 @@ type Foo2 = ReturnType<(...args: A) => string>; // Infer from an intersected tuple type Head = 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] diff --git a/tests/baselines/reference/inferTypes1.symbols b/tests/baselines/reference/inferTypes1.symbols index 587b909aaa8..d4b35b39a1a 100644 --- a/tests/baselines/reference/inferTypes1.symbols +++ b/tests/baselines/reference/inferTypes1.symbols @@ -784,8 +784,12 @@ type Head = 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)) + diff --git a/tests/baselines/reference/inferTypes1.types b/tests/baselines/reference/inferTypes1.types index e45ceef78e2..84f1a26d7ca 100644 --- a/tests/baselines/reference/inferTypes1.types +++ b/tests/baselines/reference/inferTypes1.types @@ -497,7 +497,10 @@ type Foo2 = ReturnType<(...args: A) => string>; type Head = T extends [infer THead, ...infer _] ? THead : never; >Head : Head -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" + diff --git a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols index f2c98d3cbca..b4cf7531437 100644 --- a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols +++ b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.symbols @@ -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 = +>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 : +>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 : +>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 = +>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] : +>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 = +>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 extends "|" ? ParseRows : +>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 extends "\n" | "" ? ParseRows : +>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 = { +>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 : 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 = (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 = +>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, "|">, ParseRows>> : +>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(strs: T, ...args: A): JestEach; +>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)) + +}); + diff --git a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types index 40bf04b2656..3d3d6804e1c 100644 --- a/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types +++ b/tests/baselines/reference/taggedTemplateWithSpecificTemplateStrings.types @@ -69,7 +69,7 @@ const f0_r0 = f0`a${"b"}c`; // [TemplateStringsArrayOfTemplatePrimitive : string | number | bigint | boolean +>TemplatePrimitive : string | number | bigint | boolean | null | undefined >null : null type Interpolate = @@ -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 = +>Trim : Trim + + S extends `${Chars}${infer R}` ? Trim : + S extends `${infer R}${Chars}` ? Trim : + S; + +type Split = +>Split : Split + + S extends D ? [] : + S extends `${infer H}${D}${infer T}` ? [H, ...Split] : + [S]; + +type ParseRows = +>ParseRows : ParseRows + + [A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ? + Trim extends "|" ? ParseRows : + Trim extends "\n" | "" ? ParseRows : + never : + [A, S] extends [[], readonly []] ? Rows : + never; + +type JestEachArgument = { +>JestEachArgument : JestEachArgument + + [P1 in keyof Rows]: { + [P2 in keyof Headers as P2 extends `${number}` ? Trim : never]: + P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined; + }; +}[number]; + +type JestEachFunction = (name: string, cb: (arg: Arg) => void, timeout?: number) => void; +>JestEachFunction : JestEachFunction +>name : string +>cb : (arg: Arg) => void +>arg : Arg +>timeout : number | undefined + +type JestEach = +>JestEach : JestEach + + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? + JestEachFunction, "|">, ParseRows>> : + null; +>null : null + +declare function each(strs: T, ...args: A): JestEach; +>each : (strs: T, ...args: A) => JestEach +>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 : (strs: T, ...args: A) => JestEach +>` 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 + +}); + diff --git a/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts b/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts index 402887f4cf3..fa2ad1cc401 100644 --- a/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts +++ b/tests/cases/conformance/es6/templates/taggedTemplateWithSpecificTemplateStrings.ts @@ -1,5 +1,6 @@ // @target: esnext // @noEmit: true +// @strict: true // overload resolution declare function f1(array: TemplateStringsArrayOf, ...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 `${Chars}${infer R}` ? Trim : + S extends `${infer R}${Chars}` ? Trim : + S; + +type Split = + S extends D ? [] : + S extends `${infer H}${D}${infer T}` ? [H, ...Split] : + [S]; + +type ParseRows = + [A, S] extends [[infer AH, ...infer AT], readonly [infer TH extends string, ...infer TT extends string[]]] ? + Trim extends "|" ? ParseRows : + Trim extends "\n" | "" ? ParseRows : + never : + [A, S] extends [[], readonly []] ? Rows : + never; + +type JestEachArgument = { + [P1 in keyof Rows]: { + [P2 in keyof Headers as P2 extends `${number}` ? Trim : never]: + P2 extends keyof Rows[P1] ? Rows[P1][P2] : undefined; + }; +}[number]; + +type JestEachFunction = (name: string, cb: (arg: Arg) => void, timeout?: number) => void; + +type JestEach = + T extends readonly [infer TH extends string, ...infer TT extends readonly string[]] ? + JestEachFunction, "|">, ParseRows>> : + null; + +declare function each(strs: T, ...args: A): JestEach; + +each` + foo | bar + ${"a"} | ${1} + ${"c"} | ${undefined} +`("test", ({ foo, bar }) => { + foo; + bar; +}); diff --git a/tests/cases/conformance/types/conditional/inferTypes1.ts b/tests/cases/conformance/types/conditional/inferTypes1.ts index b7dc9dcb418..61a9dc3c1d9 100644 --- a/tests/cases/conformance/types/conditional/inferTypes1.ts +++ b/tests/cases/conformance/types/conditional/inferTypes1.ts @@ -190,4 +190,5 @@ type Foo2 = ReturnType<(...args: A) => string>; // Infer from an intersected tuple type Head = 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"