Skip to content

Commit f8aa570

Browse files
authored
Get type arguments lazily for instantiating inferred type parameter constraint (microsoft#49744)
* Get type arguments lazily for instantiating inferred constraint * Use new deferred type mapper
1 parent 4c34f2c commit f8aa570

File tree

5 files changed

+469
-1
lines changed

5 files changed

+469
-1
lines changed

src/compiler/checker.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13364,7 +13364,9 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
1336413364
// type Foo<T extends string, U extends T> = [T, U];
1336513365
// type Bar<T> = T extends Foo<infer X, infer X> ? Foo<X, X> : T;
1336613366
// the instantiated constraint for U is X, so we discard that inference.
13367-
const mapper = createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReference, typeParameters));
13367+
const mapper = makeDeferredTypeMapper(typeParameters, typeParameters.map((_, index) => () => {
13368+
return getEffectiveTypeArgumentAtIndex(typeReference, typeParameters, index);
13369+
}));
1336813370
const constraint = instantiateType(declaredConstraint, mapper);
1336913371
if (constraint !== typeParameter) {
1337013372
inferences = append(inferences, constraint);
@@ -35758,6 +35760,13 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
3575835760
checkDecorators(node);
3575935761
}
3576035762

35763+
function getEffectiveTypeArgumentAtIndex(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[], index: number): Type {
35764+
if (index < typeParameters.length) {
35765+
return getTypeFromTypeNode(node.typeArguments![index]);
35766+
}
35767+
return getEffectiveTypeArguments(node, typeParameters)[index];
35768+
}
35769+
3576135770
function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[]): Type[] {
3576235771
return fillMissingTypeArguments(map(node.typeArguments!, getTypeFromTypeNode), typeParameters,
3576335772
getMinTypeArgumentCount(typeParameters), isInJSFile(node));
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//// [inferTypeConstraintInstantiationCircularity.ts]
2+
type AMappedType<T> = { [KeyType in keyof T]: number };
3+
4+
type HasM = {
5+
m: number;
6+
};
7+
8+
// Simplified repro from #48059
9+
10+
interface X1<
11+
T extends HasM,
12+
Output = AMappedType<{ s: number; } & { [k in keyof T]: number; }>
13+
> {
14+
tee: T;
15+
output: Output;
16+
}
17+
18+
type F1<T> = T extends X1<infer U> ? U : never;
19+
20+
// With default inlined
21+
22+
interface X2<
23+
T extends HasM,
24+
Output
25+
> {
26+
tee: T;
27+
output: Output;
28+
}
29+
30+
type F2<T> = T extends X2<infer U, AMappedType<{ s: number; } & { [k in keyof (infer U)]: number; }>> ? U : never;
31+
32+
// Original repro
33+
34+
type Simplify<T> = {[KeyType in keyof T]: T[KeyType]};
35+
36+
type optionalKeys<T extends object> = {
37+
[k in keyof T]: undefined extends T[k] ? k : never;
38+
}[keyof T];
39+
40+
type requiredKeys<T extends object> = Exclude<keyof T, optionalKeys<T>>;
41+
42+
export type addQuestionMarks<T extends object> = {
43+
[k in optionalKeys<T>]?: T[k];
44+
} & {
45+
[k in requiredKeys<T>]: T[k];
46+
};
47+
48+
type ZodRawShape = {
49+
[k: string]: ZodType<any>;
50+
};
51+
52+
interface ZodType<Output> {
53+
_type: Output;
54+
}
55+
56+
interface ZodObject<
57+
T extends ZodRawShape,
58+
Output = Simplify<
59+
{
60+
[k in optionalKeys<T>]?: T[k];
61+
} & {
62+
[k in requiredKeys<T>]: T[k];
63+
}
64+
>
65+
> extends ZodType<Output> {
66+
readonly _shape: T;
67+
}
68+
69+
type MyObject<T> = T extends ZodObject<infer U>
70+
? U extends ZodRawShape
71+
? U
72+
: never
73+
: never;
74+
75+
//// [inferTypeConstraintInstantiationCircularity.js]
76+
"use strict";
77+
exports.__esModule = true;
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
=== tests/cases/compiler/inferTypeConstraintInstantiationCircularity.ts ===
2+
type AMappedType<T> = { [KeyType in keyof T]: number };
3+
>AMappedType : Symbol(AMappedType, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 0))
4+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 17))
5+
>KeyType : Symbol(KeyType, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 25))
6+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 17))
7+
8+
type HasM = {
9+
>HasM : Symbol(HasM, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 55))
10+
11+
m: number;
12+
>m : Symbol(m, Decl(inferTypeConstraintInstantiationCircularity.ts, 2, 13))
13+
14+
};
15+
16+
// Simplified repro from #48059
17+
18+
interface X1<
19+
>X1 : Symbol(X1, Decl(inferTypeConstraintInstantiationCircularity.ts, 4, 2))
20+
21+
T extends HasM,
22+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 8, 13))
23+
>HasM : Symbol(HasM, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 55))
24+
25+
Output = AMappedType<{ s: number; } & { [k in keyof T]: number; }>
26+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 9, 17))
27+
>AMappedType : Symbol(AMappedType, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 0))
28+
>s : Symbol(s, Decl(inferTypeConstraintInstantiationCircularity.ts, 10, 24))
29+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 10, 43))
30+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 8, 13))
31+
32+
> {
33+
tee: T;
34+
>tee : Symbol(X1.tee, Decl(inferTypeConstraintInstantiationCircularity.ts, 11, 3))
35+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 8, 13))
36+
37+
output: Output;
38+
>output : Symbol(X1.output, Decl(inferTypeConstraintInstantiationCircularity.ts, 12, 9))
39+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 9, 17))
40+
}
41+
42+
type F1<T> = T extends X1<infer U> ? U : never;
43+
>F1 : Symbol(F1, Decl(inferTypeConstraintInstantiationCircularity.ts, 14, 1))
44+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 16, 8))
45+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 16, 8))
46+
>X1 : Symbol(X1, Decl(inferTypeConstraintInstantiationCircularity.ts, 4, 2))
47+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 16, 31))
48+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 16, 31))
49+
50+
// With default inlined
51+
52+
interface X2<
53+
>X2 : Symbol(X2, Decl(inferTypeConstraintInstantiationCircularity.ts, 16, 47))
54+
55+
T extends HasM,
56+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 20, 13))
57+
>HasM : Symbol(HasM, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 55))
58+
59+
Output
60+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 21, 17))
61+
62+
> {
63+
tee: T;
64+
>tee : Symbol(X2.tee, Decl(inferTypeConstraintInstantiationCircularity.ts, 23, 3))
65+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 20, 13))
66+
67+
output: Output;
68+
>output : Symbol(X2.output, Decl(inferTypeConstraintInstantiationCircularity.ts, 24, 9))
69+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 21, 17))
70+
}
71+
72+
type F2<T> = T extends X2<infer U, AMappedType<{ s: number; } & { [k in keyof (infer U)]: number; }>> ? U : never;
73+
>F2 : Symbol(F2, Decl(inferTypeConstraintInstantiationCircularity.ts, 26, 1))
74+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 8))
75+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 8))
76+
>X2 : Symbol(X2, Decl(inferTypeConstraintInstantiationCircularity.ts, 16, 47))
77+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 31), Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 84))
78+
>AMappedType : Symbol(AMappedType, Decl(inferTypeConstraintInstantiationCircularity.ts, 0, 0))
79+
>s : Symbol(s, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 48))
80+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 67))
81+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 31), Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 84))
82+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 31), Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 84))
83+
84+
// Original repro
85+
86+
type Simplify<T> = {[KeyType in keyof T]: T[KeyType]};
87+
>Simplify : Symbol(Simplify, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 114))
88+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 14))
89+
>KeyType : Symbol(KeyType, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 21))
90+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 14))
91+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 14))
92+
>KeyType : Symbol(KeyType, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 21))
93+
94+
type optionalKeys<T extends object> = {
95+
>optionalKeys : Symbol(optionalKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 54))
96+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 34, 18))
97+
98+
[k in keyof T]: undefined extends T[k] ? k : never;
99+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 35, 5))
100+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 34, 18))
101+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 34, 18))
102+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 35, 5))
103+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 35, 5))
104+
105+
}[keyof T];
106+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 34, 18))
107+
108+
type requiredKeys<T extends object> = Exclude<keyof T, optionalKeys<T>>;
109+
>requiredKeys : Symbol(requiredKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 36, 11))
110+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 38, 18))
111+
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
112+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 38, 18))
113+
>optionalKeys : Symbol(optionalKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 54))
114+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 38, 18))
115+
116+
export type addQuestionMarks<T extends object> = {
117+
>addQuestionMarks : Symbol(addQuestionMarks, Decl(inferTypeConstraintInstantiationCircularity.ts, 38, 72))
118+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 40, 29))
119+
120+
[k in optionalKeys<T>]?: T[k];
121+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 41, 5))
122+
>optionalKeys : Symbol(optionalKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 54))
123+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 40, 29))
124+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 40, 29))
125+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 41, 5))
126+
127+
} & {
128+
[k in requiredKeys<T>]: T[k];
129+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 43, 5))
130+
>requiredKeys : Symbol(requiredKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 36, 11))
131+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 40, 29))
132+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 40, 29))
133+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 43, 5))
134+
135+
};
136+
137+
type ZodRawShape = {
138+
>ZodRawShape : Symbol(ZodRawShape, Decl(inferTypeConstraintInstantiationCircularity.ts, 44, 2))
139+
140+
[k: string]: ZodType<any>;
141+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 47, 5))
142+
>ZodType : Symbol(ZodType, Decl(inferTypeConstraintInstantiationCircularity.ts, 48, 2))
143+
144+
};
145+
146+
interface ZodType<Output> {
147+
>ZodType : Symbol(ZodType, Decl(inferTypeConstraintInstantiationCircularity.ts, 48, 2))
148+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 50, 18))
149+
150+
_type: Output;
151+
>_type : Symbol(ZodType._type, Decl(inferTypeConstraintInstantiationCircularity.ts, 50, 27))
152+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 50, 18))
153+
}
154+
155+
interface ZodObject<
156+
>ZodObject : Symbol(ZodObject, Decl(inferTypeConstraintInstantiationCircularity.ts, 52, 1))
157+
158+
T extends ZodRawShape,
159+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 54, 20))
160+
>ZodRawShape : Symbol(ZodRawShape, Decl(inferTypeConstraintInstantiationCircularity.ts, 44, 2))
161+
162+
Output = Simplify<
163+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 55, 24))
164+
>Simplify : Symbol(Simplify, Decl(inferTypeConstraintInstantiationCircularity.ts, 28, 114))
165+
{
166+
[k in optionalKeys<T>]?: T[k];
167+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 58, 7))
168+
>optionalKeys : Symbol(optionalKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 32, 54))
169+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 54, 20))
170+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 54, 20))
171+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 58, 7))
172+
173+
} & {
174+
[k in requiredKeys<T>]: T[k];
175+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 60, 7))
176+
>requiredKeys : Symbol(requiredKeys, Decl(inferTypeConstraintInstantiationCircularity.ts, 36, 11))
177+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 54, 20))
178+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 54, 20))
179+
>k : Symbol(k, Decl(inferTypeConstraintInstantiationCircularity.ts, 60, 7))
180+
}
181+
>
182+
> extends ZodType<Output> {
183+
>ZodType : Symbol(ZodType, Decl(inferTypeConstraintInstantiationCircularity.ts, 48, 2))
184+
>Output : Symbol(Output, Decl(inferTypeConstraintInstantiationCircularity.ts, 55, 24))
185+
186+
readonly _shape: T;
187+
>_shape : Symbol(ZodObject._shape, Decl(inferTypeConstraintInstantiationCircularity.ts, 63, 27))
188+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 54, 20))
189+
}
190+
191+
type MyObject<T> = T extends ZodObject<infer U>
192+
>MyObject : Symbol(MyObject, Decl(inferTypeConstraintInstantiationCircularity.ts, 65, 1))
193+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 67, 14))
194+
>T : Symbol(T, Decl(inferTypeConstraintInstantiationCircularity.ts, 67, 14))
195+
>ZodObject : Symbol(ZodObject, Decl(inferTypeConstraintInstantiationCircularity.ts, 52, 1))
196+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 67, 44))
197+
198+
? U extends ZodRawShape
199+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 67, 44))
200+
>ZodRawShape : Symbol(ZodRawShape, Decl(inferTypeConstraintInstantiationCircularity.ts, 44, 2))
201+
202+
? U
203+
>U : Symbol(U, Decl(inferTypeConstraintInstantiationCircularity.ts, 67, 44))
204+
205+
: never
206+
: never;

0 commit comments

Comments
 (0)