Skip to content

Commit a5e6dee

Browse files
authored
Do not infer to mapped types from implied index signatures created by rest bindings (#52632)
1 parent 9901cf7 commit a5e6dee

File tree

4 files changed

+162
-1
lines changed

4 files changed

+162
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24694,7 +24694,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2469424694
if (constraintType.flags & TypeFlags.TypeParameter) {
2469524695
// We're inferring from some source type S to a mapped type { [P in K]: X }, where K is a type
2469624696
// parameter. First infer from 'keyof S' to K.
24697-
inferWithPriority(getIndexType(source), constraintType, InferencePriority.MappedTypeConstraint);
24697+
inferWithPriority(getIndexType(source, /*indexFlags*/ !!source.pattern ? IndexFlags.NoIndexSignatures : IndexFlags.None), constraintType, InferencePriority.MappedTypeConstraint);
2469824698
// If K is constrained to a type C, also infer to C. Thus, for a mapped type { [P in K]: X },
2469924699
// where K extends keyof T, we make the same inferences as for a homomorphic mapped type
2470024700
// { [P in keyof T]: X }. This enables us to make meaningful inferences when the target is a
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
=== tests/cases/compiler/objectRestBindingContextualInference.ts ===
2+
// slimmed-down repro from #52629
3+
4+
type ImageHolder<K extends string> = {
5+
>ImageHolder : Symbol(ImageHolder, Decl(objectRestBindingContextualInference.ts, 0, 0))
6+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 2, 17))
7+
8+
[P in K]: string;
9+
>P : Symbol(P, Decl(objectRestBindingContextualInference.ts, 3, 3))
10+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 2, 17))
11+
12+
};
13+
14+
type SetupImageRefs<K extends string> = {
15+
>SetupImageRefs : Symbol(SetupImageRefs, Decl(objectRestBindingContextualInference.ts, 4, 2))
16+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 6, 20))
17+
18+
[P in K]: File;
19+
>P : Symbol(P, Decl(objectRestBindingContextualInference.ts, 7, 3))
20+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 6, 20))
21+
>File : Symbol(File, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
22+
23+
};
24+
25+
type SetupImages<K extends string> = SetupImageRefs<K> & {
26+
>SetupImages : Symbol(SetupImages, Decl(objectRestBindingContextualInference.ts, 8, 2))
27+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 10, 17))
28+
>SetupImageRefs : Symbol(SetupImageRefs, Decl(objectRestBindingContextualInference.ts, 4, 2))
29+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 10, 17))
30+
31+
prepare: () => { type: K };
32+
>prepare : Symbol(prepare, Decl(objectRestBindingContextualInference.ts, 10, 58))
33+
>type : Symbol(type, Decl(objectRestBindingContextualInference.ts, 11, 18))
34+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 10, 17))
35+
36+
};
37+
38+
interface TestInterface {
39+
>TestInterface : Symbol(TestInterface, Decl(objectRestBindingContextualInference.ts, 12, 2))
40+
41+
name: string;
42+
>name : Symbol(TestInterface.name, Decl(objectRestBindingContextualInference.ts, 14, 25))
43+
44+
image: string;
45+
>image : Symbol(TestInterface.image, Decl(objectRestBindingContextualInference.ts, 15, 15))
46+
}
47+
48+
declare function setupImages<R extends ImageHolder<K>, K extends string>(
49+
>setupImages : Symbol(setupImages, Decl(objectRestBindingContextualInference.ts, 17, 1))
50+
>R : Symbol(R, Decl(objectRestBindingContextualInference.ts, 19, 29))
51+
>ImageHolder : Symbol(ImageHolder, Decl(objectRestBindingContextualInference.ts, 0, 0))
52+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 19, 54))
53+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 19, 54))
54+
55+
item: R,
56+
>item : Symbol(item, Decl(objectRestBindingContextualInference.ts, 19, 73))
57+
>R : Symbol(R, Decl(objectRestBindingContextualInference.ts, 19, 29))
58+
59+
keys: K[]
60+
>keys : Symbol(keys, Decl(objectRestBindingContextualInference.ts, 20, 10))
61+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 19, 54))
62+
63+
): SetupImages<K>;
64+
>SetupImages : Symbol(SetupImages, Decl(objectRestBindingContextualInference.ts, 8, 2))
65+
>K : Symbol(K, Decl(objectRestBindingContextualInference.ts, 19, 54))
66+
67+
declare const test: TestInterface;
68+
>test : Symbol(test, Decl(objectRestBindingContextualInference.ts, 24, 13))
69+
>TestInterface : Symbol(TestInterface, Decl(objectRestBindingContextualInference.ts, 12, 2))
70+
71+
const { prepare, ...rest } = setupImages(test, ["image"]);
72+
>prepare : Symbol(prepare, Decl(objectRestBindingContextualInference.ts, 26, 7))
73+
>rest : Symbol(rest, Decl(objectRestBindingContextualInference.ts, 26, 16))
74+
>setupImages : Symbol(setupImages, Decl(objectRestBindingContextualInference.ts, 17, 1))
75+
>test : Symbol(test, Decl(objectRestBindingContextualInference.ts, 24, 13))
76+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
=== tests/cases/compiler/objectRestBindingContextualInference.ts ===
2+
// slimmed-down repro from #52629
3+
4+
type ImageHolder<K extends string> = {
5+
>ImageHolder : ImageHolder<K>
6+
7+
[P in K]: string;
8+
};
9+
10+
type SetupImageRefs<K extends string> = {
11+
>SetupImageRefs : SetupImageRefs<K>
12+
13+
[P in K]: File;
14+
};
15+
16+
type SetupImages<K extends string> = SetupImageRefs<K> & {
17+
>SetupImages : SetupImages<K>
18+
19+
prepare: () => { type: K };
20+
>prepare : () => { type: K;}
21+
>type : K
22+
23+
};
24+
25+
interface TestInterface {
26+
name: string;
27+
>name : string
28+
29+
image: string;
30+
>image : string
31+
}
32+
33+
declare function setupImages<R extends ImageHolder<K>, K extends string>(
34+
>setupImages : <R extends ImageHolder<K>, K extends string>(item: R, keys: K[]) => SetupImages<K>
35+
36+
item: R,
37+
>item : R
38+
39+
keys: K[]
40+
>keys : K[]
41+
42+
): SetupImages<K>;
43+
44+
declare const test: TestInterface;
45+
>test : TestInterface
46+
47+
const { prepare, ...rest } = setupImages(test, ["image"]);
48+
>prepare : () => { type: "image"; }
49+
>rest : { image: File; }
50+
>setupImages(test, ["image"]) : SetupImages<"image">
51+
>setupImages : <R extends ImageHolder<K>, K extends string>(item: R, keys: K[]) => SetupImages<K>
52+
>test : TestInterface
53+
>["image"] : "image"[]
54+
>"image" : "image"
55+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// slimmed-down repro from #52629
5+
6+
type ImageHolder<K extends string> = {
7+
[P in K]: string;
8+
};
9+
10+
type SetupImageRefs<K extends string> = {
11+
[P in K]: File;
12+
};
13+
14+
type SetupImages<K extends string> = SetupImageRefs<K> & {
15+
prepare: () => { type: K };
16+
};
17+
18+
interface TestInterface {
19+
name: string;
20+
image: string;
21+
}
22+
23+
declare function setupImages<R extends ImageHolder<K>, K extends string>(
24+
item: R,
25+
keys: K[]
26+
): SetupImages<K>;
27+
28+
declare const test: TestInterface;
29+
30+
const { prepare, ...rest } = setupImages(test, ["image"]);

0 commit comments

Comments
 (0)