Skip to content

Commit 683e281

Browse files
authored
Reintroduce cloneInferredPartOfContext to fix overloaded inferences with returnMappers (#33478)
1 parent 1c20aa0 commit 683e281

File tree

5 files changed

+298
-1
lines changed

5 files changed

+298
-1
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15408,6 +15408,13 @@ namespace ts {
1540815408
};
1540915409
}
1541015410

15411+
function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined {
15412+
const inferences = filter(context.inferences, hasInferenceCandidates);
15413+
return inferences.length ?
15414+
createInferenceContextWorker(map(inferences, cloneInferenceInfo), context.signature, context.flags, context.compareTypes) :
15415+
undefined;
15416+
}
15417+
1541115418
function getMapperFromContext<T extends InferenceContext | undefined>(context: T): TypeMapper | T & undefined {
1541215419
return context && context.mapper;
1541315420
}
@@ -21465,7 +21472,7 @@ namespace ts {
2146521472
const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags);
2146621473
const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper);
2146721474
inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType);
21468-
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(returnContext) : undefined;
21475+
context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined;
2146921476
}
2147021477
}
2147121478

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [twiceNestedKeyofIndexInference.ts]
2+
type Set1<T, K1 extends keyof T> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
3+
[SK1 in K1]-?: Required<Pick<T, SK1>>;
4+
}[K1];
5+
6+
type Set2<T, K1 extends keyof T, K2 extends keyof T[K1]> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
7+
[SK1 in K1]-?: Required<{
8+
[key in K1]: Set1<T[K1], K2>;
9+
}>;
10+
}[K1];
11+
12+
declare function set<T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>;
13+
14+
declare function set<T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>;
15+
16+
17+
interface State {
18+
a: {
19+
b: string;
20+
c: number;
21+
};
22+
d: boolean;
23+
}
24+
25+
const state: State = {
26+
a: {
27+
b: "",
28+
c: 0,
29+
},
30+
d: false,
31+
};
32+
33+
const newState: State = set(state, ["a", 'b'], 'why'); // shouldn't be an error
34+
35+
//// [twiceNestedKeyofIndexInference.js]
36+
var state = {
37+
a: {
38+
b: "",
39+
c: 0
40+
},
41+
d: false
42+
};
43+
var newState = set(state, ["a", 'b'], 'why'); // shouldn't be an error
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
=== tests/cases/compiler/twiceNestedKeyofIndexInference.ts ===
2+
type Set1<T, K1 extends keyof T> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
3+
>Set1 : Symbol(Set1, Decl(twiceNestedKeyofIndexInference.ts, 0, 0))
4+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
5+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 0, 12))
6+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
7+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
8+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
9+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
10+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
11+
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
12+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
13+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 0, 12))
14+
15+
[SK1 in K1]-?: Required<Pick<T, SK1>>;
16+
>SK1 : Symbol(SK1, Decl(twiceNestedKeyofIndexInference.ts, 1, 5))
17+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 0, 12))
18+
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
19+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
20+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 0, 10))
21+
>SK1 : Symbol(SK1, Decl(twiceNestedKeyofIndexInference.ts, 1, 5))
22+
23+
}[K1];
24+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 0, 12))
25+
26+
type Set2<T, K1 extends keyof T, K2 extends keyof T[K1]> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
27+
>Set2 : Symbol(Set2, Decl(twiceNestedKeyofIndexInference.ts, 2, 6))
28+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
29+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
30+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
31+
>K2 : Symbol(K2, Decl(twiceNestedKeyofIndexInference.ts, 4, 32))
32+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
33+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
34+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
35+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
36+
>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --))
37+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
38+
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
39+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
40+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
41+
42+
[SK1 in K1]-?: Required<{
43+
>SK1 : Symbol(SK1, Decl(twiceNestedKeyofIndexInference.ts, 5, 5))
44+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
45+
>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --))
46+
47+
[key in K1]: Set1<T[K1], K2>;
48+
>key : Symbol(key, Decl(twiceNestedKeyofIndexInference.ts, 6, 9))
49+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
50+
>Set1 : Symbol(Set1, Decl(twiceNestedKeyofIndexInference.ts, 0, 0))
51+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 4, 10))
52+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
53+
>K2 : Symbol(K2, Decl(twiceNestedKeyofIndexInference.ts, 4, 32))
54+
55+
}>;
56+
}[K1];
57+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 4, 12))
58+
59+
declare function set<T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>;
60+
>set : Symbol(set, Decl(twiceNestedKeyofIndexInference.ts, 8, 6), Decl(twiceNestedKeyofIndexInference.ts, 10, 94))
61+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 10, 21))
62+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 10, 23))
63+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 10, 21))
64+
>source : Symbol(source, Decl(twiceNestedKeyofIndexInference.ts, 10, 44))
65+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 10, 21))
66+
>path : Symbol(path, Decl(twiceNestedKeyofIndexInference.ts, 10, 54))
67+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 10, 23))
68+
>value : Symbol(value, Decl(twiceNestedKeyofIndexInference.ts, 10, 66))
69+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 10, 21))
70+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 10, 23))
71+
>Set1 : Symbol(Set1, Decl(twiceNestedKeyofIndexInference.ts, 0, 0))
72+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 10, 21))
73+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 10, 23))
74+
75+
declare function set<T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>;
76+
>set : Symbol(set, Decl(twiceNestedKeyofIndexInference.ts, 8, 6), Decl(twiceNestedKeyofIndexInference.ts, 10, 94))
77+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 12, 21))
78+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 12, 23))
79+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 12, 21))
80+
>K2 : Symbol(K2, Decl(twiceNestedKeyofIndexInference.ts, 12, 43))
81+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 12, 21))
82+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 12, 23))
83+
>source : Symbol(source, Decl(twiceNestedKeyofIndexInference.ts, 12, 68))
84+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 12, 21))
85+
>path : Symbol(path, Decl(twiceNestedKeyofIndexInference.ts, 12, 78))
86+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 12, 23))
87+
>K2 : Symbol(K2, Decl(twiceNestedKeyofIndexInference.ts, 12, 43))
88+
>value : Symbol(value, Decl(twiceNestedKeyofIndexInference.ts, 12, 94))
89+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 12, 21))
90+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 12, 23))
91+
>K2 : Symbol(K2, Decl(twiceNestedKeyofIndexInference.ts, 12, 43))
92+
>Set2 : Symbol(Set2, Decl(twiceNestedKeyofIndexInference.ts, 2, 6))
93+
>T : Symbol(T, Decl(twiceNestedKeyofIndexInference.ts, 12, 21))
94+
>K1 : Symbol(K1, Decl(twiceNestedKeyofIndexInference.ts, 12, 23))
95+
>K2 : Symbol(K2, Decl(twiceNestedKeyofIndexInference.ts, 12, 43))
96+
97+
98+
interface State {
99+
>State : Symbol(State, Decl(twiceNestedKeyofIndexInference.ts, 12, 130))
100+
101+
a: {
102+
>a : Symbol(State.a, Decl(twiceNestedKeyofIndexInference.ts, 15, 17))
103+
104+
b: string;
105+
>b : Symbol(b, Decl(twiceNestedKeyofIndexInference.ts, 16, 8))
106+
107+
c: number;
108+
>c : Symbol(c, Decl(twiceNestedKeyofIndexInference.ts, 17, 18))
109+
110+
};
111+
d: boolean;
112+
>d : Symbol(State.d, Decl(twiceNestedKeyofIndexInference.ts, 19, 6))
113+
}
114+
115+
const state: State = {
116+
>state : Symbol(state, Decl(twiceNestedKeyofIndexInference.ts, 23, 5))
117+
>State : Symbol(State, Decl(twiceNestedKeyofIndexInference.ts, 12, 130))
118+
119+
a: {
120+
>a : Symbol(a, Decl(twiceNestedKeyofIndexInference.ts, 23, 22))
121+
122+
b: "",
123+
>b : Symbol(b, Decl(twiceNestedKeyofIndexInference.ts, 24, 8))
124+
125+
c: 0,
126+
>c : Symbol(c, Decl(twiceNestedKeyofIndexInference.ts, 25, 14))
127+
128+
},
129+
d: false,
130+
>d : Symbol(d, Decl(twiceNestedKeyofIndexInference.ts, 27, 6))
131+
132+
};
133+
134+
const newState: State = set(state, ["a", 'b'], 'why'); // shouldn't be an error
135+
>newState : Symbol(newState, Decl(twiceNestedKeyofIndexInference.ts, 31, 5))
136+
>State : Symbol(State, Decl(twiceNestedKeyofIndexInference.ts, 12, 130))
137+
>set : Symbol(set, Decl(twiceNestedKeyofIndexInference.ts, 8, 6), Decl(twiceNestedKeyofIndexInference.ts, 10, 94))
138+
>state : Symbol(state, Decl(twiceNestedKeyofIndexInference.ts, 23, 5))
139+
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
=== tests/cases/compiler/twiceNestedKeyofIndexInference.ts ===
2+
type Set1<T, K1 extends keyof T> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
3+
>Set1 : Set1<T, K1>
4+
5+
[SK1 in K1]-?: Required<Pick<T, SK1>>;
6+
}[K1];
7+
8+
type Set2<T, K1 extends keyof T, K2 extends keyof T[K1]> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
9+
>Set2 : Set2<T, K1, K2>
10+
11+
[SK1 in K1]-?: Required<{
12+
[key in K1]: Set1<T[K1], K2>;
13+
}>;
14+
}[K1];
15+
16+
declare function set<T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>;
17+
>set : { <T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>; <T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>; }
18+
>source : T
19+
>path : [K1]
20+
>value : T[K1]
21+
22+
declare function set<T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>;
23+
>set : { <T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>; <T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>; }
24+
>source : T
25+
>path : [K1, K2]
26+
>value : T[K1][K2]
27+
28+
29+
interface State {
30+
a: {
31+
>a : { b: string; c: number; }
32+
33+
b: string;
34+
>b : string
35+
36+
c: number;
37+
>c : number
38+
39+
};
40+
d: boolean;
41+
>d : boolean
42+
}
43+
44+
const state: State = {
45+
>state : State
46+
>{ a: { b: "", c: 0, }, d: false,} : { a: { b: string; c: number; }; d: false; }
47+
48+
a: {
49+
>a : { b: string; c: number; }
50+
>{ b: "", c: 0, } : { b: string; c: number; }
51+
52+
b: "",
53+
>b : string
54+
>"" : ""
55+
56+
c: 0,
57+
>c : number
58+
>0 : 0
59+
60+
},
61+
d: false,
62+
>d : false
63+
>false : false
64+
65+
};
66+
67+
const newState: State = set(state, ["a", 'b'], 'why'); // shouldn't be an error
68+
>newState : State
69+
>set(state, ["a", 'b'], 'why') : Pick<State, "d"> & Required<{ a: Pick<{ b: string; c: number; }, "c"> & Required<Pick<{ b: string; c: number; }, "b">>; }>
70+
>set : { <T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>; <T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>; }
71+
>state : State
72+
>["a", 'b'] : ["a", "b"]
73+
>"a" : "a"
74+
>'b' : "b"
75+
>'why' : "why"
76+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
type Set1<T, K1 extends keyof T> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
2+
[SK1 in K1]-?: Required<Pick<T, SK1>>;
3+
}[K1];
4+
5+
type Set2<T, K1 extends keyof T, K2 extends keyof T[K1]> = T extends any[] ? T : Pick<T, Exclude<keyof T, K1>> & {
6+
[SK1 in K1]-?: Required<{
7+
[key in K1]: Set1<T[K1], K2>;
8+
}>;
9+
}[K1];
10+
11+
declare function set<T, K1 extends keyof T>(source: T, path: [K1], value: T[K1]): Set1<T, K1>;
12+
13+
declare function set<T, K1 extends keyof T, K2 extends keyof T[K1]>(source: T, path: [K1, K2], value: T[K1][K2]): Set2<T, K1, K2>;
14+
15+
16+
interface State {
17+
a: {
18+
b: string;
19+
c: number;
20+
};
21+
d: boolean;
22+
}
23+
24+
const state: State = {
25+
a: {
26+
b: "",
27+
c: 0,
28+
},
29+
d: false,
30+
};
31+
32+
const newState: State = set(state, ["a", 'b'], 'why'); // shouldn't be an error

0 commit comments

Comments
 (0)