Skip to content

Commit 2b85a29

Browse files
committed
Apply isLiteralContextualType recursively for unions and intersections.
Fixes microsoft#19632. The issue was isLiteralContextualType was only checking for type parameters that extended a literal base type at the top level. It was already recursively checking the constituents of unions and intersections but it did so using maybeTypeOfKind which only compared type flags matching literal or index. Also adds a test case that failed before this change and succeeds now.
1 parent 1a7a587 commit 2b85a29

File tree

5 files changed

+57
-1
lines changed

5 files changed

+57
-1
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18458,7 +18458,17 @@ namespace ts {
1845818458
}
1845918459
contextualType = constraint;
1846018460
}
18461-
return maybeTypeOfKind(contextualType, (TypeFlags.Literal | TypeFlags.Index));
18461+
if (contextualType.flags & (TypeFlags.Literal | TypeFlags.Index)) {
18462+
return true;
18463+
}
18464+
if (contextualType.flags & TypeFlags.UnionOrIntersection) {
18465+
const types = (<UnionOrIntersectionType>contextualType).types;
18466+
for (const t of types) {
18467+
if (isLiteralContextualType(t)) {
18468+
return true;
18469+
}
18470+
}
18471+
}
1846218472
}
1846318473
return false;
1846418474
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//// [genericCallStringLiteralUnionNested.ts]
2+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>;
3+
const result: {z: string} = nestedUnion({ fields: "z" });
4+
5+
6+
//// [genericCallStringLiteralUnionNested.js]
7+
var result = nestedUnion({ fields: "z" });
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/compiler/genericCallStringLiteralUnionNested.ts ===
2+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>;
3+
>nestedUnion : Symbol(nestedUnion, Decl(genericCallStringLiteralUnionNested.ts, 0, 0))
4+
>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 29))
5+
>a : Symbol(a, Decl(genericCallStringLiteralUnionNested.ts, 0, 47))
6+
>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 0, 51))
7+
>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 29))
8+
>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 29))
9+
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
10+
>A : Symbol(A, Decl(genericCallStringLiteralUnionNested.ts, 0, 29))
11+
12+
const result: {z: string} = nestedUnion({ fields: "z" });
13+
>result : Symbol(result, Decl(genericCallStringLiteralUnionNested.ts, 1, 5))
14+
>z : Symbol(z, Decl(genericCallStringLiteralUnionNested.ts, 1, 15))
15+
>nestedUnion : Symbol(nestedUnion, Decl(genericCallStringLiteralUnionNested.ts, 0, 0))
16+
>fields : Symbol(fields, Decl(genericCallStringLiteralUnionNested.ts, 1, 41))
17+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/compiler/genericCallStringLiteralUnionNested.ts ===
2+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>;
3+
>nestedUnion : <A extends string>(a: { fields: A | A[]; }) => Record<A, string>
4+
>A : A
5+
>a : { fields: A | A[]; }
6+
>fields : A | A[]
7+
>A : A
8+
>A : A
9+
>Record : Record<K, T>
10+
>A : A
11+
12+
const result: {z: string} = nestedUnion({ fields: "z" });
13+
>result : { z: string; }
14+
>z : string
15+
>nestedUnion({ fields: "z" }) : Record<"z", string>
16+
>nestedUnion : <A extends string>(a: { fields: A | A[]; }) => Record<A, string>
17+
>{ fields: "z" } : { fields: "z"; }
18+
>fields : string
19+
>"z" : "z"
20+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>;
2+
const result: {z: string} = nestedUnion({ fields: "z" });

0 commit comments

Comments
 (0)