Skip to content

Commit 9c1bd45

Browse files
committed
As requested, include fix for microsoft#19632
1 parent 840c600 commit 9c1bd45

File tree

5 files changed

+236
-5
lines changed

5 files changed

+236
-5
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18451,13 +18451,17 @@ namespace ts {
1845118451

1845218452
function isLiteralContextualType(contextualType: Type, candidateLiteral: Type): boolean {
1845318453
if (contextualType) {
18454+
if (contextualType.flags & TypeFlags.UnionOrIntersection) {
18455+
return some((contextualType as UnionOrIntersectionType).types, t => isLiteralContextualType(t, candidateLiteral));
18456+
}
1845418457
if (contextualType.flags & TypeFlags.TypeVariable) {
1845518458
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
1845618459
return isLiteralContextualType(constraint, candidateLiteral);
1845718460
}
18458-
return !!((maybeTypeOfKind(contextualType, TypeFlags.StringLike) && maybeTypeOfKind(candidateLiteral, TypeFlags.StringLike)) ||
18459-
(maybeTypeOfKind(contextualType, TypeFlags.NumberLike) && maybeTypeOfKind(candidateLiteral, TypeFlags.NumberLike)) ||
18460-
(maybeTypeOfKind(contextualType, TypeFlags.BooleanLike) && maybeTypeOfKind(candidateLiteral, TypeFlags.BooleanLike)));
18461+
// No need to `maybeTypeOfKind` on the contextual type, as it can't be a union, _however_, `candidateLiteral` might still be one!
18462+
return !!(((contextualType.flags & TypeFlags.StringLike) && maybeTypeOfKind(candidateLiteral, TypeFlags.StringLike)) ||
18463+
((contextualType.flags & TypeFlags.NumberLike) && maybeTypeOfKind(candidateLiteral, TypeFlags.NumberLike)) ||
18464+
((contextualType.flags & TypeFlags.BooleanLike) && maybeTypeOfKind(candidateLiteral, TypeFlags.BooleanLike)));
1846118465
}
1846218466
return false;
1846318467
}
@@ -18467,8 +18471,8 @@ namespace ts {
1846718471
contextualType = getContextualType(node);
1846818472
}
1846918473
const type = checkExpression(node, checkMode);
18470-
const shouldWiden = isTypeAssertion(node) || isLiteralContextualType(contextualType, type);
18471-
return shouldWiden ? type : getWidenedLiteralType(type);
18474+
const shouldNotWiden = isTypeAssertion(node) || isLiteralContextualType(contextualType, type);
18475+
return shouldNotWiden ? type : getWidenedLiteralType(type);
1847218476
}
1847318477

1847418478
function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [nestedTypevariableInfersLiteral.ts]
2+
// https://github.com/Microsoft/TypeScript/issues/19632
3+
declare function direct<A extends string>(a: A | A[]): Record<A, string>
4+
declare function nested<A extends string>(a: { fields: A }): Record<A, string>
5+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>
6+
7+
const directUnionSingle = direct("z")
8+
const directUnionArray = direct(["z", "y"])
9+
const nestedSingle = nested({fields: "z"})
10+
const nestedUnionSingle = nestedUnion({fields: "z"})
11+
const nestedUnionArray = nestedUnion({fields: ["z", "y"]})
12+
13+
declare function hasZField(arg: { z: string }): void
14+
15+
hasZField(directUnionSingle) // ok
16+
hasZField(directUnionArray) // ok
17+
hasZField(nestedSingle) // ok
18+
hasZField(nestedUnionSingle) // ok
19+
hasZField(nestedUnionArray) // ok
20+
21+
//// [nestedTypevariableInfersLiteral.js]
22+
var directUnionSingle = direct("z");
23+
var directUnionArray = direct(["z", "y"]);
24+
var nestedSingle = nested({ fields: "z" });
25+
var nestedUnionSingle = nestedUnion({ fields: "z" });
26+
var nestedUnionArray = nestedUnion({ fields: ["z", "y"] });
27+
hasZField(directUnionSingle); // ok
28+
hasZField(directUnionArray); // ok
29+
hasZField(nestedSingle); // ok
30+
hasZField(nestedUnionSingle); // ok
31+
hasZField(nestedUnionArray); // ok
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
=== tests/cases/compiler/nestedTypevariableInfersLiteral.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/19632
3+
declare function direct<A extends string>(a: A | A[]): Record<A, string>
4+
>direct : Symbol(direct, Decl(nestedTypevariableInfersLiteral.ts, 0, 0))
5+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 1, 24))
6+
>a : Symbol(a, Decl(nestedTypevariableInfersLiteral.ts, 1, 42))
7+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 1, 24))
8+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 1, 24))
9+
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
10+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 1, 24))
11+
12+
declare function nested<A extends string>(a: { fields: A }): Record<A, string>
13+
>nested : Symbol(nested, Decl(nestedTypevariableInfersLiteral.ts, 1, 72))
14+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 2, 24))
15+
>a : Symbol(a, Decl(nestedTypevariableInfersLiteral.ts, 2, 42))
16+
>fields : Symbol(fields, Decl(nestedTypevariableInfersLiteral.ts, 2, 46))
17+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 2, 24))
18+
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
19+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 2, 24))
20+
21+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>
22+
>nestedUnion : Symbol(nestedUnion, Decl(nestedTypevariableInfersLiteral.ts, 2, 78))
23+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 3, 29))
24+
>a : Symbol(a, Decl(nestedTypevariableInfersLiteral.ts, 3, 47))
25+
>fields : Symbol(fields, Decl(nestedTypevariableInfersLiteral.ts, 3, 51))
26+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 3, 29))
27+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 3, 29))
28+
>Record : Symbol(Record, Decl(lib.d.ts, --, --))
29+
>A : Symbol(A, Decl(nestedTypevariableInfersLiteral.ts, 3, 29))
30+
31+
const directUnionSingle = direct("z")
32+
>directUnionSingle : Symbol(directUnionSingle, Decl(nestedTypevariableInfersLiteral.ts, 5, 5))
33+
>direct : Symbol(direct, Decl(nestedTypevariableInfersLiteral.ts, 0, 0))
34+
35+
const directUnionArray = direct(["z", "y"])
36+
>directUnionArray : Symbol(directUnionArray, Decl(nestedTypevariableInfersLiteral.ts, 6, 5))
37+
>direct : Symbol(direct, Decl(nestedTypevariableInfersLiteral.ts, 0, 0))
38+
39+
const nestedSingle = nested({fields: "z"})
40+
>nestedSingle : Symbol(nestedSingle, Decl(nestedTypevariableInfersLiteral.ts, 7, 5))
41+
>nested : Symbol(nested, Decl(nestedTypevariableInfersLiteral.ts, 1, 72))
42+
>fields : Symbol(fields, Decl(nestedTypevariableInfersLiteral.ts, 7, 29))
43+
44+
const nestedUnionSingle = nestedUnion({fields: "z"})
45+
>nestedUnionSingle : Symbol(nestedUnionSingle, Decl(nestedTypevariableInfersLiteral.ts, 8, 5))
46+
>nestedUnion : Symbol(nestedUnion, Decl(nestedTypevariableInfersLiteral.ts, 2, 78))
47+
>fields : Symbol(fields, Decl(nestedTypevariableInfersLiteral.ts, 8, 39))
48+
49+
const nestedUnionArray = nestedUnion({fields: ["z", "y"]})
50+
>nestedUnionArray : Symbol(nestedUnionArray, Decl(nestedTypevariableInfersLiteral.ts, 9, 5))
51+
>nestedUnion : Symbol(nestedUnion, Decl(nestedTypevariableInfersLiteral.ts, 2, 78))
52+
>fields : Symbol(fields, Decl(nestedTypevariableInfersLiteral.ts, 9, 38))
53+
54+
declare function hasZField(arg: { z: string }): void
55+
>hasZField : Symbol(hasZField, Decl(nestedTypevariableInfersLiteral.ts, 9, 58))
56+
>arg : Symbol(arg, Decl(nestedTypevariableInfersLiteral.ts, 11, 27))
57+
>z : Symbol(z, Decl(nestedTypevariableInfersLiteral.ts, 11, 33))
58+
59+
hasZField(directUnionSingle) // ok
60+
>hasZField : Symbol(hasZField, Decl(nestedTypevariableInfersLiteral.ts, 9, 58))
61+
>directUnionSingle : Symbol(directUnionSingle, Decl(nestedTypevariableInfersLiteral.ts, 5, 5))
62+
63+
hasZField(directUnionArray) // ok
64+
>hasZField : Symbol(hasZField, Decl(nestedTypevariableInfersLiteral.ts, 9, 58))
65+
>directUnionArray : Symbol(directUnionArray, Decl(nestedTypevariableInfersLiteral.ts, 6, 5))
66+
67+
hasZField(nestedSingle) // ok
68+
>hasZField : Symbol(hasZField, Decl(nestedTypevariableInfersLiteral.ts, 9, 58))
69+
>nestedSingle : Symbol(nestedSingle, Decl(nestedTypevariableInfersLiteral.ts, 7, 5))
70+
71+
hasZField(nestedUnionSingle) // ok
72+
>hasZField : Symbol(hasZField, Decl(nestedTypevariableInfersLiteral.ts, 9, 58))
73+
>nestedUnionSingle : Symbol(nestedUnionSingle, Decl(nestedTypevariableInfersLiteral.ts, 8, 5))
74+
75+
hasZField(nestedUnionArray) // ok
76+
>hasZField : Symbol(hasZField, Decl(nestedTypevariableInfersLiteral.ts, 9, 58))
77+
>nestedUnionArray : Symbol(nestedUnionArray, Decl(nestedTypevariableInfersLiteral.ts, 9, 5))
78+
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
=== tests/cases/compiler/nestedTypevariableInfersLiteral.ts ===
2+
// https://github.com/Microsoft/TypeScript/issues/19632
3+
declare function direct<A extends string>(a: A | A[]): Record<A, string>
4+
>direct : <A extends string>(a: A | A[]) => Record<A, string>
5+
>A : A
6+
>a : A | A[]
7+
>A : A
8+
>A : A
9+
>Record : Record<K, T>
10+
>A : A
11+
12+
declare function nested<A extends string>(a: { fields: A }): Record<A, string>
13+
>nested : <A extends string>(a: { fields: A; }) => Record<A, string>
14+
>A : A
15+
>a : { fields: A; }
16+
>fields : A
17+
>A : A
18+
>Record : Record<K, T>
19+
>A : A
20+
21+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>
22+
>nestedUnion : <A extends string>(a: { fields: A | A[]; }) => Record<A, string>
23+
>A : A
24+
>a : { fields: A | A[]; }
25+
>fields : A | A[]
26+
>A : A
27+
>A : A
28+
>Record : Record<K, T>
29+
>A : A
30+
31+
const directUnionSingle = direct("z")
32+
>directUnionSingle : Record<"z", string>
33+
>direct("z") : Record<"z", string>
34+
>direct : <A extends string>(a: A | A[]) => Record<A, string>
35+
>"z" : "z"
36+
37+
const directUnionArray = direct(["z", "y"])
38+
>directUnionArray : Record<"z" | "y", string>
39+
>direct(["z", "y"]) : Record<"z" | "y", string>
40+
>direct : <A extends string>(a: A | A[]) => Record<A, string>
41+
>["z", "y"] : ("z" | "y")[]
42+
>"z" : "z"
43+
>"y" : "y"
44+
45+
const nestedSingle = nested({fields: "z"})
46+
>nestedSingle : Record<"z", string>
47+
>nested({fields: "z"}) : Record<"z", string>
48+
>nested : <A extends string>(a: { fields: A; }) => Record<A, string>
49+
>{fields: "z"} : { fields: "z"; }
50+
>fields : string
51+
>"z" : "z"
52+
53+
const nestedUnionSingle = nestedUnion({fields: "z"})
54+
>nestedUnionSingle : Record<"z", string>
55+
>nestedUnion({fields: "z"}) : Record<"z", string>
56+
>nestedUnion : <A extends string>(a: { fields: A | A[]; }) => Record<A, string>
57+
>{fields: "z"} : { fields: "z"; }
58+
>fields : string
59+
>"z" : "z"
60+
61+
const nestedUnionArray = nestedUnion({fields: ["z", "y"]})
62+
>nestedUnionArray : Record<"z" | "y", string>
63+
>nestedUnion({fields: ["z", "y"]}) : Record<"z" | "y", string>
64+
>nestedUnion : <A extends string>(a: { fields: A | A[]; }) => Record<A, string>
65+
>{fields: ["z", "y"]} : { fields: ("z" | "y")[]; }
66+
>fields : ("z" | "y")[]
67+
>["z", "y"] : ("z" | "y")[]
68+
>"z" : "z"
69+
>"y" : "y"
70+
71+
declare function hasZField(arg: { z: string }): void
72+
>hasZField : (arg: { z: string; }) => void
73+
>arg : { z: string; }
74+
>z : string
75+
76+
hasZField(directUnionSingle) // ok
77+
>hasZField(directUnionSingle) : void
78+
>hasZField : (arg: { z: string; }) => void
79+
>directUnionSingle : Record<"z", string>
80+
81+
hasZField(directUnionArray) // ok
82+
>hasZField(directUnionArray) : void
83+
>hasZField : (arg: { z: string; }) => void
84+
>directUnionArray : Record<"z" | "y", string>
85+
86+
hasZField(nestedSingle) // ok
87+
>hasZField(nestedSingle) : void
88+
>hasZField : (arg: { z: string; }) => void
89+
>nestedSingle : Record<"z", string>
90+
91+
hasZField(nestedUnionSingle) // ok
92+
>hasZField(nestedUnionSingle) : void
93+
>hasZField : (arg: { z: string; }) => void
94+
>nestedUnionSingle : Record<"z", string>
95+
96+
hasZField(nestedUnionArray) // ok
97+
>hasZField(nestedUnionArray) : void
98+
>hasZField : (arg: { z: string; }) => void
99+
>nestedUnionArray : Record<"z" | "y", string>
100+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// https://github.com/Microsoft/TypeScript/issues/19632
2+
declare function direct<A extends string>(a: A | A[]): Record<A, string>
3+
declare function nested<A extends string>(a: { fields: A }): Record<A, string>
4+
declare function nestedUnion<A extends string>(a: { fields: A | A[] }): Record<A, string>
5+
6+
const directUnionSingle = direct("z")
7+
const directUnionArray = direct(["z", "y"])
8+
const nestedSingle = nested({fields: "z"})
9+
const nestedUnionSingle = nestedUnion({fields: "z"})
10+
const nestedUnionArray = nestedUnion({fields: ["z", "y"]})
11+
12+
declare function hasZField(arg: { z: string }): void
13+
14+
hasZField(directUnionSingle) // ok
15+
hasZField(directUnionArray) // ok
16+
hasZField(nestedSingle) // ok
17+
hasZField(nestedUnionSingle) // ok
18+
hasZField(nestedUnionArray) // ok

0 commit comments

Comments
 (0)