Skip to content

Commit 1a27fd9

Browse files
committed
Fixed an issue with apparent mapped type keys
1 parent a9460c8 commit 1a27fd9

8 files changed

Lines changed: 620 additions & 1 deletion

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22486,7 +22486,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2248622486
/*stringsOnly*/ false,
2248722487
t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t))),
2248822488
);
22489-
return getUnionType(mappedKeys);
22489+
return mappedKeys.length ? getUnionType(mappedKeys) : stringNumberSymbolType;
2249022490
}
2249122491

2249222492
function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType<typeof captureErrorCalculationState>): Ternary {

tests/baselines/reference/keyRemappingKeyofResult.js renamed to tests/baselines/reference/keyRemappingKeyofResult(strict=false).js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ function g<T>() {
7171
x = "str";
7272
}
7373

74+
// https://github.com/microsoft/TypeScript/issues/57827
75+
76+
type StringKeys<T> = Extract<
77+
keyof {
78+
[P in keyof T as T[P] extends string ? P : never]: any;
79+
},
80+
string
81+
>;
82+
83+
function test_57827<T>(z: StringKeys<T>) {
84+
const f: string = z;
85+
}
86+
7487
export {};
7588

7689
//// [keyRemappingKeyofResult.js]
@@ -98,4 +111,7 @@ function g() {
98111
x = sym;
99112
x = "str";
100113
}
114+
function test_57827(z) {
115+
const f = z;
116+
}
101117
export {};

tests/baselines/reference/keyRemappingKeyofResult.symbols renamed to tests/baselines/reference/keyRemappingKeyofResult(strict=false).symbols

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,35 @@ function g<T>() {
192192
>x : Symbol(x, Decl(keyRemappingKeyofResult.ts, 65, 7))
193193
}
194194

195+
// https://github.com/microsoft/TypeScript/issues/57827
196+
197+
type StringKeys<T> = Extract<
198+
>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 68, 1))
199+
>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16))
200+
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --))
201+
202+
keyof {
203+
[P in keyof T as T[P] extends string ? P : never]: any;
204+
>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5))
205+
>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16))
206+
>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 72, 16))
207+
>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5))
208+
>P : Symbol(P, Decl(keyRemappingKeyofResult.ts, 74, 5))
209+
210+
},
211+
string
212+
>;
213+
214+
function test_57827<T>(z: StringKeys<T>) {
215+
>test_57827 : Symbol(test_57827, Decl(keyRemappingKeyofResult.ts, 77, 2))
216+
>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 79, 20))
217+
>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23))
218+
>StringKeys : Symbol(StringKeys, Decl(keyRemappingKeyofResult.ts, 68, 1))
219+
>T : Symbol(T, Decl(keyRemappingKeyofResult.ts, 79, 20))
220+
221+
const f: string = z;
222+
>f : Symbol(f, Decl(keyRemappingKeyofResult.ts, 80, 7))
223+
>z : Symbol(z, Decl(keyRemappingKeyofResult.ts, 79, 23))
224+
}
225+
195226
export {};

tests/baselines/reference/keyRemappingKeyofResult.types renamed to tests/baselines/reference/keyRemappingKeyofResult(strict=false).types

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,24 @@ function g<T>() {
172172
>"str" : "str"
173173
}
174174

175+
// https://github.com/microsoft/TypeScript/issues/57827
176+
177+
type StringKeys<T> = Extract<
178+
>StringKeys : StringKeys<T>
179+
180+
keyof {
181+
[P in keyof T as T[P] extends string ? P : never]: any;
182+
},
183+
string
184+
>;
185+
186+
function test_57827<T>(z: StringKeys<T>) {
187+
>test_57827 : <T>(z: StringKeys<T>) => void
188+
>z : Extract<keyof { [P in keyof T as T[P] extends string ? P : never]: any; }, string>
189+
190+
const f: string = z;
191+
>f : string
192+
>z : Extract<keyof { [P in keyof T as T[P] extends string ? P : never]: any; }, string>
193+
}
194+
175195
export {};
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//// [tests/cases/compiler/keyRemappingKeyofResult.ts] ////
2+
3+
//// [keyRemappingKeyofResult.ts]
4+
const sym = Symbol("")
5+
type Orig = { [k: string]: any, str: any, [sym]: any }
6+
7+
type Okay = Exclude<keyof Orig, never>
8+
// type Okay = string | number | typeof sym
9+
10+
type Remapped = { [K in keyof Orig as {} extends Record<K, any> ? never : K]: any }
11+
/* type Remapped = {
12+
str: any;
13+
[sym]: any;
14+
} */
15+
// no string index signature, right?
16+
17+
type Oops = Exclude<keyof Remapped, never>
18+
declare let x: Oops;
19+
x = sym;
20+
x = "str";
21+
// type Oops = typeof sym <-- what happened to "str"?
22+
23+
// equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute):
24+
function f<T>() {
25+
type Orig = { [k: string]: any, str: any, [sym]: any } & T;
26+
27+
type Okay = keyof Orig;
28+
let a: Okay;
29+
a = "str";
30+
a = sym;
31+
a = "whatever";
32+
// type Okay = string | number | typeof sym
33+
34+
type Remapped = { [K in keyof Orig as {} extends Record<K, any> ? never : K]: any }
35+
/* type Remapped = {
36+
str: any;
37+
[sym]: any;
38+
} */
39+
// no string index signature, right?
40+
41+
type Oops = keyof Remapped;
42+
let x: Oops;
43+
x = sym;
44+
x = "str";
45+
}
46+
47+
// and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType`
48+
function g<T>() {
49+
type Orig = { [k: string]: any, str: any, [sym]: any } & T;
50+
51+
type Okay = keyof Orig;
52+
let a: Okay;
53+
a = "str";
54+
a = sym;
55+
a = "whatever";
56+
// type Okay = string | number | typeof sym
57+
58+
type NonIndex<T extends PropertyKey> = {} extends Record<T, any> ? never : T;
59+
type DistributiveNonIndex<T extends PropertyKey> = T extends unknown ? NonIndex<T> : never;
60+
61+
type Remapped = { [K in keyof Orig as DistributiveNonIndex<K>]: any }
62+
/* type Remapped = {
63+
str: any;
64+
[sym]: any;
65+
} */
66+
// no string index signature, right?
67+
68+
type Oops = keyof Remapped;
69+
let x: Oops;
70+
x = sym;
71+
x = "str";
72+
}
73+
74+
// https://github.com/microsoft/TypeScript/issues/57827
75+
76+
type StringKeys<T> = Extract<
77+
keyof {
78+
[P in keyof T as T[P] extends string ? P : never]: any;
79+
},
80+
string
81+
>;
82+
83+
function test_57827<T>(z: StringKeys<T>) {
84+
const f: string = z;
85+
}
86+
87+
export {};
88+
89+
//// [keyRemappingKeyofResult.js]
90+
const sym = Symbol("");
91+
x = sym;
92+
x = "str";
93+
// type Oops = typeof sym <-- what happened to "str"?
94+
// equivalently, with an unresolved generic (no `exclude` shenanigans, since conditions won't execute):
95+
function f() {
96+
let a;
97+
a = "str";
98+
a = sym;
99+
a = "whatever";
100+
let x;
101+
x = sym;
102+
x = "str";
103+
}
104+
// and another generic case with a _distributive_ mapping, to trigger a different branch in `getIndexType`
105+
function g() {
106+
let a;
107+
a = "str";
108+
a = sym;
109+
a = "whatever";
110+
let x;
111+
x = sym;
112+
x = "str";
113+
}
114+
function test_57827(z) {
115+
const f = z;
116+
}
117+
export {};

0 commit comments

Comments
 (0)