diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 09354d957a36e..1bcc98cf3ed64 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -18446,7 +18446,7 @@ namespace ts { isTypeAssertion(declaration.initializer) ? type : getWidenedLiteralType(type); } - function isLiteralContextualType(contextualType: Type) { + function isLiteralContextualType(contextualType: Type): boolean { if (contextualType) { if (contextualType.flags & TypeFlags.TypeVariable) { const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType; @@ -18458,7 +18458,9 @@ namespace ts { } contextualType = constraint; } - return maybeTypeOfKind(contextualType, (TypeFlags.Literal | TypeFlags.Index)); + return !!(contextualType.flags & (TypeFlags.Literal | TypeFlags.Index) || + contextualType.flags & TypeFlags.UnionOrIntersection + && forEach((contextualType).types, isLiteralContextualType)); } return false; } diff --git a/tests/baselines/reference/genericCallStringLiteralUnionNested.errors.txt b/tests/baselines/reference/genericCallStringLiteralUnionNested.errors.txt new file mode 100644 index 0000000000000..1dca2533612a7 --- /dev/null +++ b/tests/baselines/reference/genericCallStringLiteralUnionNested.errors.txt @@ -0,0 +1,50 @@ +tests/cases/compiler/genericCallStringLiteralUnionNested.ts(23,7): error TS2322: Type 'string[]' is not assignable to type '"z"[]'. + Type 'string' is not assignable to type '"z"'. +tests/cases/compiler/genericCallStringLiteralUnionNested.ts(24,7): error TS2322: Type 'number[]' is not assignable to type '1[]'. + Type 'number' is not assignable to type '1'. +tests/cases/compiler/genericCallStringLiteralUnionNested.ts(27,7): error TS2322: Type 'string[]' is not assignable to type '"z"[]'. +tests/cases/compiler/genericCallStringLiteralUnionNested.ts(28,7): error TS2322: Type 'number[]' is not assignable to type '3[]'. + Type 'number' is not assignable to type '3'. + + +==== tests/cases/compiler/genericCallStringLiteralUnionNested.ts (4 errors) ==== + declare function nestedUnionExtendsString(a: { fields: A | A[] }): Record; + const t1: {z: string} = nestedUnionExtendsString({ fields: "z" }); + + declare function nestedUnionExtendsLiterals(a: { fields: A | A[] }): A[]; + const t2: "z"[] = nestedUnionExtendsLiterals({ fields: "z" }); + + declare function nestedGenericIntersection(a: { fields: A | A[] }, b: B[], c: C[]): A[]; + const t3: "z"[] = nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]); + + declare function nestedUnionExtendsNumber(a: { fields: A | A[] }): A[]; + const t4: 1[] = nestedUnionExtendsNumber({ fields: 1 }); + + declare function nestedUnionExtendsLiteralsNumber(a: { fields: A | A[] }): A[]; + const t5: 2[] = nestedUnionExtendsLiteralsNumber({ fields: 2 }); + + declare function nestedUnionIntersectionGenericNumber(a: { fields: A | A[] }, b: B[], c: C[]): A[]; + const t6: 3[] = nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]); + + + // The following are expected to fail because they don't have an extend string or extend number generic constraint. + + declare function nestedUnionPlain(a: { fields: A | A[] }): A[]; + const expectedFail1: "z"[] = nestedUnionPlain({ fields: "z" }); + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'string[]' is not assignable to type '"z"[]'. +!!! error TS2322: Type 'string' is not assignable to type '"z"'. + const expectedFail2: 1[] = nestedUnionPlain({ fields: 1 }); + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'number[]' is not assignable to type '1[]'. +!!! error TS2322: Type 'number' is not assignable to type '1'. + + declare function nestedUnionIntersectionPlainGenerics(a: { fields: A | A[] }, b: B[], c: C[]): A[]; + const expectedFail3: "z"[] = nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]); + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'string[]' is not assignable to type '"z"[]'. + const expectedFail4: 3[] = nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]); + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'number[]' is not assignable to type '3[]'. +!!! error TS2322: Type 'number' is not assignable to type '3'. + \ No newline at end of file diff --git a/tests/baselines/reference/genericCallStringLiteralUnionNested.js b/tests/baselines/reference/genericCallStringLiteralUnionNested.js new file mode 100644 index 0000000000000..706674a1414ea --- /dev/null +++ b/tests/baselines/reference/genericCallStringLiteralUnionNested.js @@ -0,0 +1,42 @@ +//// [genericCallStringLiteralUnionNested.ts] +declare function nestedUnionExtendsString(a: { fields: A | A[] }): Record; +const t1: {z: string} = nestedUnionExtendsString({ fields: "z" }); + +declare function nestedUnionExtendsLiterals(a: { fields: A | A[] }): A[]; +const t2: "z"[] = nestedUnionExtendsLiterals({ fields: "z" }); + +declare function nestedGenericIntersection(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +const t3: "z"[] = nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]); + +declare function nestedUnionExtendsNumber(a: { fields: A | A[] }): A[]; +const t4: 1[] = nestedUnionExtendsNumber({ fields: 1 }); + +declare function nestedUnionExtendsLiteralsNumber(a: { fields: A | A[] }): A[]; +const t5: 2[] = nestedUnionExtendsLiteralsNumber({ fields: 2 }); + +declare function nestedUnionIntersectionGenericNumber(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +const t6: 3[] = nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]); + + +// The following are expected to fail because they don't have an extend string or extend number generic constraint. + +declare function nestedUnionPlain(a: { fields: A | A[] }): A[]; +const expectedFail1: "z"[] = nestedUnionPlain({ fields: "z" }); +const expectedFail2: 1[] = nestedUnionPlain({ fields: 1 }); + +declare function nestedUnionIntersectionPlainGenerics(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +const expectedFail3: "z"[] = nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]); +const expectedFail4: 3[] = nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]); + + +//// [genericCallStringLiteralUnionNested.js] +var t1 = nestedUnionExtendsString({ fields: "z" }); +var t2 = nestedUnionExtendsLiterals({ fields: "z" }); +var t3 = nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]); +var t4 = nestedUnionExtendsNumber({ fields: 1 }); +var t5 = nestedUnionExtendsLiteralsNumber({ fields: 2 }); +var t6 = nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]); +var expectedFail1 = nestedUnionPlain({ fields: "z" }); +var expectedFail2 = nestedUnionPlain({ fields: 1 }); +var expectedFail3 = nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]); +var expectedFail4 = nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]); diff --git a/tests/baselines/reference/genericCallStringLiteralUnionNested.symbols b/tests/baselines/reference/genericCallStringLiteralUnionNested.symbols new file mode 100644 index 0000000000000..eb8d26d4bcc78 --- /dev/null +++ b/tests/baselines/reference/genericCallStringLiteralUnionNested.symbols @@ -0,0 +1,152 @@ +=== tests/cases/compiler/genericCallStringLiteralUnionNested.ts === +declare function nestedUnionExtendsString(a: { fields: A | A[] }): Record; +>nestedUnionExtendsString : Symbol(nestedUnionExtendsString, Decl(genericCallStringLiteralUnionNested.ts, 0, 0)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 42)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 0, 60)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 0, 64)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 42)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 42)) +>Record : Symbol(Record, Decl(lib.d.ts, --, --)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 42)) + +const t1: {z: string} = nestedUnionExtendsString({ fields: "z" }); +>t1 : Symbol(t1, Decl(genericCallStringLiteralUnionNested.ts, 1, 5)) +>z : Symbol(z, Decl(genericCallStringLiteralUnionNested.ts, 1, 11)) +>nestedUnionExtendsString : Symbol(nestedUnionExtendsString, Decl(genericCallStringLiteralUnionNested.ts, 0, 0)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 1, 50)) + +declare function nestedUnionExtendsLiterals(a: { fields: A | A[] }): A[]; +>nestedUnionExtendsLiterals : Symbol(nestedUnionExtendsLiterals, Decl(genericCallStringLiteralUnionNested.ts, 1, 66)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 3, 44)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 3, 65)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 3, 69)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 3, 44)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 3, 44)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 3, 44)) + +const t2: "z"[] = nestedUnionExtendsLiterals({ fields: "z" }); +>t2 : Symbol(t2, Decl(genericCallStringLiteralUnionNested.ts, 4, 5)) +>nestedUnionExtendsLiterals : Symbol(nestedUnionExtendsLiterals, Decl(genericCallStringLiteralUnionNested.ts, 1, 66)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 4, 46)) + +declare function nestedGenericIntersection(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +>nestedGenericIntersection : Symbol(nestedGenericIntersection, Decl(genericCallStringLiteralUnionNested.ts, 4, 62)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 6, 43)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 6, 59)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 6, 77)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 6, 59)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 6, 77)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 6, 96)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 6, 100)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 6, 43)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 6, 43)) +>b : Symbol(b, Decl(genericCallStringLiteralUnionNested.ts, 6, 119)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 6, 59)) +>c : Symbol(c, Decl(genericCallStringLiteralUnionNested.ts, 6, 127)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 6, 77)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 6, 43)) + +const t3: "z"[] = nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]); +>t3 : Symbol(t3, Decl(genericCallStringLiteralUnionNested.ts, 7, 5)) +>nestedGenericIntersection : Symbol(nestedGenericIntersection, Decl(genericCallStringLiteralUnionNested.ts, 4, 62)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 7, 45)) + +declare function nestedUnionExtendsNumber(a: { fields: A | A[] }): A[]; +>nestedUnionExtendsNumber : Symbol(nestedUnionExtendsNumber, Decl(genericCallStringLiteralUnionNested.ts, 7, 85)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 9, 42)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 9, 60)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 9, 64)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 9, 42)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 9, 42)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 9, 42)) + +const t4: 1[] = nestedUnionExtendsNumber({ fields: 1 }); +>t4 : Symbol(t4, Decl(genericCallStringLiteralUnionNested.ts, 10, 5)) +>nestedUnionExtendsNumber : Symbol(nestedUnionExtendsNumber, Decl(genericCallStringLiteralUnionNested.ts, 7, 85)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 10, 42)) + +declare function nestedUnionExtendsLiteralsNumber(a: { fields: A | A[] }): A[]; +>nestedUnionExtendsLiteralsNumber : Symbol(nestedUnionExtendsLiteralsNumber, Decl(genericCallStringLiteralUnionNested.ts, 10, 56)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 12, 50)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 12, 67)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 12, 71)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 12, 50)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 12, 50)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 12, 50)) + +const t5: 2[] = nestedUnionExtendsLiteralsNumber({ fields: 2 }); +>t5 : Symbol(t5, Decl(genericCallStringLiteralUnionNested.ts, 13, 5)) +>nestedUnionExtendsLiteralsNumber : Symbol(nestedUnionExtendsLiteralsNumber, Decl(genericCallStringLiteralUnionNested.ts, 10, 56)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 13, 50)) + +declare function nestedUnionIntersectionGenericNumber(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +>nestedUnionIntersectionGenericNumber : Symbol(nestedUnionIntersectionGenericNumber, Decl(genericCallStringLiteralUnionNested.ts, 13, 64)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 15, 54)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 15, 70)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 15, 88)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 15, 70)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 15, 88)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 15, 107)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 15, 111)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 15, 54)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 15, 54)) +>b : Symbol(b, Decl(genericCallStringLiteralUnionNested.ts, 15, 130)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 15, 70)) +>c : Symbol(c, Decl(genericCallStringLiteralUnionNested.ts, 15, 138)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 15, 88)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 15, 54)) + +const t6: 3[] = nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]); +>t6 : Symbol(t6, Decl(genericCallStringLiteralUnionNested.ts, 16, 5)) +>nestedUnionIntersectionGenericNumber : Symbol(nestedUnionIntersectionGenericNumber, Decl(genericCallStringLiteralUnionNested.ts, 13, 64)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 16, 54)) + + +// The following are expected to fail because they don't have an extend string or extend number generic constraint. + +declare function nestedUnionPlain(a: { fields: A | A[] }): A[]; +>nestedUnionPlain : Symbol(nestedUnionPlain, Decl(genericCallStringLiteralUnionNested.ts, 16, 84)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 21, 34)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 21, 37)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 21, 41)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 21, 34)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 21, 34)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 21, 34)) + +const expectedFail1: "z"[] = nestedUnionPlain({ fields: "z" }); +>expectedFail1 : Symbol(expectedFail1, Decl(genericCallStringLiteralUnionNested.ts, 22, 5)) +>nestedUnionPlain : Symbol(nestedUnionPlain, Decl(genericCallStringLiteralUnionNested.ts, 16, 84)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 22, 47)) + +const expectedFail2: 1[] = nestedUnionPlain({ fields: 1 }); +>expectedFail2 : Symbol(expectedFail2, Decl(genericCallStringLiteralUnionNested.ts, 23, 5)) +>nestedUnionPlain : Symbol(nestedUnionPlain, Decl(genericCallStringLiteralUnionNested.ts, 16, 84)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 23, 45)) + +declare function nestedUnionIntersectionPlainGenerics(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +>nestedUnionIntersectionPlainGenerics : Symbol(nestedUnionIntersectionPlainGenerics, Decl(genericCallStringLiteralUnionNested.ts, 23, 59)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 25, 54)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 25, 70)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 25, 73)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 25, 70)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 25, 73)) +>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 25, 77)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 25, 81)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 25, 54)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 25, 54)) +>b : Symbol(b, Decl(genericCallStringLiteralUnionNested.ts, 25, 100)) +>B : Symbol(B, Decl(genericCallStringLiteralUnionNested.ts, 25, 70)) +>c : Symbol(c, Decl(genericCallStringLiteralUnionNested.ts, 25, 108)) +>C : Symbol(C, Decl(genericCallStringLiteralUnionNested.ts, 25, 73)) +>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 25, 54)) + +const expectedFail3: "z"[] = nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]); +>expectedFail3 : Symbol(expectedFail3, Decl(genericCallStringLiteralUnionNested.ts, 26, 5)) +>nestedUnionIntersectionPlainGenerics : Symbol(nestedUnionIntersectionPlainGenerics, Decl(genericCallStringLiteralUnionNested.ts, 23, 59)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 26, 67)) + +const expectedFail4: 3[] = nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]); +>expectedFail4 : Symbol(expectedFail4, Decl(genericCallStringLiteralUnionNested.ts, 27, 5)) +>nestedUnionIntersectionPlainGenerics : Symbol(nestedUnionIntersectionPlainGenerics, Decl(genericCallStringLiteralUnionNested.ts, 23, 59)) +>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 27, 65)) + diff --git a/tests/baselines/reference/genericCallStringLiteralUnionNested.types b/tests/baselines/reference/genericCallStringLiteralUnionNested.types new file mode 100644 index 0000000000000..ef8a341b40ced --- /dev/null +++ b/tests/baselines/reference/genericCallStringLiteralUnionNested.types @@ -0,0 +1,206 @@ +=== tests/cases/compiler/genericCallStringLiteralUnionNested.ts === +declare function nestedUnionExtendsString(a: { fields: A | A[] }): Record; +>nestedUnionExtendsString : (a: { fields: A | A[]; }) => Record +>A : A +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>Record : Record +>A : A + +const t1: {z: string} = nestedUnionExtendsString({ fields: "z" }); +>t1 : { z: string; } +>z : string +>nestedUnionExtendsString({ fields: "z" }) : Record<"z", string> +>nestedUnionExtendsString : (a: { fields: A | A[]; }) => Record +>{ fields: "z" } : { fields: "z"; } +>fields : string +>"z" : "z" + +declare function nestedUnionExtendsLiterals(a: { fields: A | A[] }): A[]; +>nestedUnionExtendsLiterals : (a: { fields: A | A[]; }) => A[] +>A : A +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>A : A + +const t2: "z"[] = nestedUnionExtendsLiterals({ fields: "z" }); +>t2 : "z"[] +>nestedUnionExtendsLiterals({ fields: "z" }) : "z"[] +>nestedUnionExtendsLiterals : (a: { fields: A | A[]; }) => A[] +>{ fields: "z" } : { fields: "z"; } +>fields : string +>"z" : "z" + +declare function nestedGenericIntersection(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +>nestedGenericIntersection : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>A : A +>B : B +>C : C +>B : B +>C : C +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>b : B[] +>B : B +>c : C[] +>C : C +>A : A + +const t3: "z"[] = nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]); +>t3 : "z"[] +>nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]) : "z"[] +>nestedGenericIntersection : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>{ fields: "z" } : { fields: "z"; } +>fields : string +>"z" : "z" +>["z", "y"] : ("z" | "y")[] +>"z" : "z" +>"y" : "y" +>["z", "y"] : ("z" | "y")[] +>"z" : "z" +>"y" : "y" + +declare function nestedUnionExtendsNumber(a: { fields: A | A[] }): A[]; +>nestedUnionExtendsNumber : (a: { fields: A | A[]; }) => A[] +>A : A +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>A : A + +const t4: 1[] = nestedUnionExtendsNumber({ fields: 1 }); +>t4 : 1[] +>nestedUnionExtendsNumber({ fields: 1 }) : 1[] +>nestedUnionExtendsNumber : (a: { fields: A | A[]; }) => A[] +>{ fields: 1 } : { fields: 1; } +>fields : number +>1 : 1 + +declare function nestedUnionExtendsLiteralsNumber(a: { fields: A | A[] }): A[]; +>nestedUnionExtendsLiteralsNumber : (a: { fields: A | A[]; }) => A[] +>A : A +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>A : A + +const t5: 2[] = nestedUnionExtendsLiteralsNumber({ fields: 2 }); +>t5 : 2[] +>nestedUnionExtendsLiteralsNumber({ fields: 2 }) : 2[] +>nestedUnionExtendsLiteralsNumber : (a: { fields: A | A[]; }) => A[] +>{ fields: 2 } : { fields: 2; } +>fields : number +>2 : 2 + +declare function nestedUnionIntersectionGenericNumber(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +>nestedUnionIntersectionGenericNumber : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>A : A +>B : B +>C : C +>B : B +>C : C +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>b : B[] +>B : B +>c : C[] +>C : C +>A : A + +const t6: 3[] = nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]); +>t6 : 3[] +>nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]) : 3[] +>nestedUnionIntersectionGenericNumber : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>{ fields: 3 } : { fields: 3; } +>fields : number +>3 : 3 +>[1, 3] : (1 | 3)[] +>1 : 1 +>3 : 3 +>[1, 3] : (1 | 3)[] +>1 : 1 +>3 : 3 + + +// The following are expected to fail because they don't have an extend string or extend number generic constraint. + +declare function nestedUnionPlain(a: { fields: A | A[] }): A[]; +>nestedUnionPlain : (a: { fields: A | A[]; }) => A[] +>A : A +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>A : A + +const expectedFail1: "z"[] = nestedUnionPlain({ fields: "z" }); +>expectedFail1 : "z"[] +>nestedUnionPlain({ fields: "z" }) : string[] +>nestedUnionPlain : (a: { fields: A | A[]; }) => A[] +>{ fields: "z" } : { fields: string; } +>fields : string +>"z" : "z" + +const expectedFail2: 1[] = nestedUnionPlain({ fields: 1 }); +>expectedFail2 : 1[] +>nestedUnionPlain({ fields: 1 }) : number[] +>nestedUnionPlain : (a: { fields: A | A[]; }) => A[] +>{ fields: 1 } : { fields: number; } +>fields : number +>1 : 1 + +declare function nestedUnionIntersectionPlainGenerics(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +>nestedUnionIntersectionPlainGenerics : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>A : A +>B : B +>C : C +>B : B +>C : C +>a : { fields: A | A[]; } +>fields : A | A[] +>A : A +>A : A +>b : B[] +>B : B +>c : C[] +>C : C +>A : A + +const expectedFail3: "z"[] = nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]); +>expectedFail3 : "z"[] +>nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]) : string[] +>nestedUnionIntersectionPlainGenerics : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>{ fields: "z" } : { fields: string; } +>fields : string +>"z" : "z" +>["z", "y"] : string[] +>"z" : "z" +>"y" : "y" +>["z", "y"] : string[] +>"z" : "z" +>"y" : "y" + +const expectedFail4: 3[] = nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]); +>expectedFail4 : 3[] +>nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]) : number[] +>nestedUnionIntersectionPlainGenerics : (a: { fields: A | A[]; }, b: B[], c: C[]) => A[] +>{ fields: 3 } : { fields: number; } +>fields : number +>3 : 3 +>[1, 3] : number[] +>1 : 1 +>3 : 3 +>[1, 3] : number[] +>1 : 1 +>3 : 3 + diff --git a/tests/cases/compiler/genericCallStringLiteralUnionNested.ts b/tests/cases/compiler/genericCallStringLiteralUnionNested.ts new file mode 100644 index 0000000000000..81ed587294ed7 --- /dev/null +++ b/tests/cases/compiler/genericCallStringLiteralUnionNested.ts @@ -0,0 +1,28 @@ +declare function nestedUnionExtendsString(a: { fields: A | A[] }): Record; +const t1: {z: string} = nestedUnionExtendsString({ fields: "z" }); + +declare function nestedUnionExtendsLiterals(a: { fields: A | A[] }): A[]; +const t2: "z"[] = nestedUnionExtendsLiterals({ fields: "z" }); + +declare function nestedGenericIntersection(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +const t3: "z"[] = nestedGenericIntersection({ fields: "z" }, ["z", "y"], ["z", "y"]); + +declare function nestedUnionExtendsNumber(a: { fields: A | A[] }): A[]; +const t4: 1[] = nestedUnionExtendsNumber({ fields: 1 }); + +declare function nestedUnionExtendsLiteralsNumber(a: { fields: A | A[] }): A[]; +const t5: 2[] = nestedUnionExtendsLiteralsNumber({ fields: 2 }); + +declare function nestedUnionIntersectionGenericNumber(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +const t6: 3[] = nestedUnionIntersectionGenericNumber({ fields: 3 }, [1, 3], [1, 3]); + + +// The following are expected to fail because they don't have an extend string or extend number generic constraint. + +declare function nestedUnionPlain(a: { fields: A | A[] }): A[]; +const expectedFail1: "z"[] = nestedUnionPlain({ fields: "z" }); +const expectedFail2: 1[] = nestedUnionPlain({ fields: 1 }); + +declare function nestedUnionIntersectionPlainGenerics(a: { fields: A | A[] }, b: B[], c: C[]): A[]; +const expectedFail3: "z"[] = nestedUnionIntersectionPlainGenerics({ fields: "z" }, ["z", "y"], ["z", "y"]); +const expectedFail4: 3[] = nestedUnionIntersectionPlainGenerics({ fields: 3 }, [1, 3], [1, 3]);