Skip to content

Commit eed8573

Browse files
authored
Merge pull request #21271 from Microsoft/infer-keyof-to-any-not-empty
Inference of string literals to keyof creates an object with props of type `any`, not `{}`
2 parents 4632ed6 + f0b4018 commit eed8573

5 files changed

+63
-29
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10966,7 +10966,7 @@ namespace ts {
1096610966
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
1096710967
}
1096810968

10969-
/** Create an object with properties named in the string literal type. Every property has type `{}` */
10969+
/** Create an object with properties named in the string literal type. Every property has type `any` */
1097010970
function createEmptyObjectTypeFromStringLiteral(type: Type) {
1097110971
const members = createSymbolTable();
1097210972
forEachType(type, t => {
@@ -10975,7 +10975,7 @@ namespace ts {
1097510975
}
1097610976
const name = escapeLeadingUnderscores((t as StringLiteralType).value);
1097710977
const literalProp = createSymbol(SymbolFlags.Property, name);
10978-
literalProp.type = emptyObjectType;
10978+
literalProp.type = anyType;
1097910979
if (t.symbol) {
1098010980
literalProp.declarations = t.symbol.declarations;
1098110981
literalProp.valueDeclaration = t.symbol.valueDeclaration;
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
//// [inferObjectTypeFromStringLiteralToKeyof.ts]
2-
declare function inference<T>(target: T, name: keyof T): void;
2+
declare function inference1<T>(name: keyof T): T;
3+
declare function inference2<T>(target: T, name: keyof T): T;
34
declare var two: "a" | "d";
4-
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
5+
const x = inference1(two);
6+
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
57

68

79
//// [inferObjectTypeFromStringLiteralToKeyof.js]
8-
inference({ a: 1, b: 2, c: 3, d: function (n) { return n; } }, two);
10+
var x = inference1(two);
11+
var y = inference2({ a: 1, b: 2, c: 3, d: function (n) { return n; } }, two);
Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
=== tests/cases/compiler/inferObjectTypeFromStringLiteralToKeyof.ts ===
2-
declare function inference<T>(target: T, name: keyof T): void;
3-
>inference : Symbol(inference, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
4-
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 27))
5-
>target : Symbol(target, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 30))
6-
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 27))
7-
>name : Symbol(name, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 40))
8-
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 27))
2+
declare function inference1<T>(name: keyof T): T;
3+
>inference1 : Symbol(inference1, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
4+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 28))
5+
>name : Symbol(name, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 31))
6+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 28))
7+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 28))
8+
9+
declare function inference2<T>(target: T, name: keyof T): T;
10+
>inference2 : Symbol(inference2, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 49))
11+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
12+
>target : Symbol(target, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 31))
13+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
14+
>name : Symbol(name, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 41))
15+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
16+
>T : Symbol(T, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 28))
917

1018
declare var two: "a" | "d";
11-
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 11))
19+
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
20+
21+
const x = inference1(two);
22+
>x : Symbol(x, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 3, 5))
23+
>inference1 : Symbol(inference1, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
24+
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
1225

13-
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
14-
>inference : Symbol(inference, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 0))
15-
>a : Symbol(a, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
16-
>b : Symbol(b, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 17))
17-
>c : Symbol(c, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 23))
18-
>d : Symbol(d, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 29))
19-
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 32))
20-
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 32))
21-
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 1, 11))
26+
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
27+
>y : Symbol(y, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 5))
28+
>inference2 : Symbol(inference2, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 0, 49))
29+
>a : Symbol(a, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 22))
30+
>b : Symbol(b, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 28))
31+
>c : Symbol(c, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 34))
32+
>d : Symbol(d, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 40))
33+
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 43))
34+
>n : Symbol(n, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 4, 43))
35+
>two : Symbol(two, Decl(inferObjectTypeFromStringLiteralToKeyof.ts, 2, 11))
2236

tests/baselines/reference/inferObjectTypeFromStringLiteralToKeyof.types

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
11
=== tests/cases/compiler/inferObjectTypeFromStringLiteralToKeyof.ts ===
2-
declare function inference<T>(target: T, name: keyof T): void;
3-
>inference : <T>(target: T, name: keyof T) => void
2+
declare function inference1<T>(name: keyof T): T;
3+
>inference1 : <T>(name: keyof T) => T
4+
>T : T
5+
>name : keyof T
6+
>T : T
7+
>T : T
8+
9+
declare function inference2<T>(target: T, name: keyof T): T;
10+
>inference2 : <T>(target: T, name: keyof T) => T
411
>T : T
512
>target : T
613
>T : T
714
>name : keyof T
815
>T : T
16+
>T : T
917

1018
declare var two: "a" | "d";
1119
>two : "a" | "d"
1220

13-
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
14-
>inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two) : void
15-
>inference : <T>(target: T, name: keyof T) => void
21+
const x = inference1(two);
22+
>x : { a: any; d: any; }
23+
>inference1(two) : { a: any; d: any; }
24+
>inference1 : <T>(name: keyof T) => T
25+
>two : "a" | "d"
26+
27+
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
28+
>y : { a: number; b: number; c: number; d(n: any): any; }
29+
>inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two) : { a: number; b: number; c: number; d(n: any): any; }
30+
>inference2 : <T>(target: T, name: keyof T) => T
1631
>{ a: 1, b: 2, c: 3, d(n) { return n } } : { a: number; b: number; c: number; d(n: any): any; }
1732
>a : number
1833
>1 : 1
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
declare function inference<T>(target: T, name: keyof T): void;
1+
declare function inference1<T>(name: keyof T): T;
2+
declare function inference2<T>(target: T, name: keyof T): T;
23
declare var two: "a" | "d";
3-
inference({ a: 1, b: 2, c: 3, d(n) { return n } }, two);
4+
const x = inference1(two);
5+
const y = inference2({ a: 1, b: 2, c: 3, d(n) { return n } }, two);

0 commit comments

Comments
 (0)