Skip to content

Commit 78089b4

Browse files
authored
Add intra expression inference sites based on JSX attributes (#52837)
1 parent 2b9d792 commit 78089b4

File tree

4 files changed

+692
-3
lines changed

4 files changed

+692
-3
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30230,7 +30230,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3023030230
*/
3023130231
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) {
3023230232
const attributes = openingLikeElement.attributes;
30233-
const attributesType = getContextualType(attributes, ContextFlags.None);
30233+
const contextualType = getContextualType(attributes, ContextFlags.None);
3023430234
const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined;
3023530235
let attributesTable = createSymbolTable();
3023630236
let spread: Type = emptyJsxObjectType;
@@ -30259,12 +30259,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3025930259
if (attributeDecl.name.escapedText === jsxChildrenPropertyName) {
3026030260
explicitlySpecifyChildrenAttribute = true;
3026130261
}
30262-
if (attributesType) {
30263-
const prop = getPropertyOfType(attributesType, member.escapedName);
30262+
if (contextualType) {
30263+
const prop = getPropertyOfType(contextualType, member.escapedName);
3026430264
if (prop && prop.declarations && isDeprecatedSymbol(prop)) {
3026530265
addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string);
3026630266
}
3026730267
}
30268+
if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(attributeDecl)) {
30269+
const inferenceContext = getInferenceContext(attributes);
30270+
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
30271+
const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!;
30272+
addIntraExpressionInferenceSite(inferenceContext, inferenceNode, exprType);
30273+
}
3026830274
}
3026930275
else {
3027030276
Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute);
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
=== tests/cases/conformance/types/typeRelationships/typeInference/intraExpressionInferencesJsx.tsx ===
2+
/// <reference path="react16.d.ts" />
3+
4+
// repro from #52798
5+
6+
type A = {
7+
>A : Symbol(A, Decl(intraExpressionInferencesJsx.tsx, 0, 0))
8+
9+
a: boolean;
10+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 4, 10))
11+
12+
};
13+
14+
type B = {
15+
>B : Symbol(B, Decl(intraExpressionInferencesJsx.tsx, 6, 2))
16+
17+
b: string;
18+
>b : Symbol(b, Decl(intraExpressionInferencesJsx.tsx, 8, 10))
19+
20+
};
21+
22+
type C = {
23+
>C : Symbol(C, Decl(intraExpressionInferencesJsx.tsx, 10, 2))
24+
25+
c: number;
26+
>c : Symbol(c, Decl(intraExpressionInferencesJsx.tsx, 12, 10))
27+
28+
};
29+
30+
type Animations = {
31+
>Animations : Symbol(Animations, Decl(intraExpressionInferencesJsx.tsx, 14, 2))
32+
33+
[key: string]: { value: number } & (
34+
>key : Symbol(key, Decl(intraExpressionInferencesJsx.tsx, 17, 3))
35+
>value : Symbol(value, Decl(intraExpressionInferencesJsx.tsx, 17, 18))
36+
37+
| ({ kind: "a"; func?(): Partial<A> } & A)
38+
>kind : Symbol(kind, Decl(intraExpressionInferencesJsx.tsx, 18, 8))
39+
>func : Symbol(func, Decl(intraExpressionInferencesJsx.tsx, 18, 19))
40+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
41+
>A : Symbol(A, Decl(intraExpressionInferencesJsx.tsx, 0, 0))
42+
>A : Symbol(A, Decl(intraExpressionInferencesJsx.tsx, 0, 0))
43+
44+
| ({ kind: "b"; func?(): Partial<B> } & B)
45+
>kind : Symbol(kind, Decl(intraExpressionInferencesJsx.tsx, 19, 8))
46+
>func : Symbol(func, Decl(intraExpressionInferencesJsx.tsx, 19, 19))
47+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
48+
>B : Symbol(B, Decl(intraExpressionInferencesJsx.tsx, 6, 2))
49+
>B : Symbol(B, Decl(intraExpressionInferencesJsx.tsx, 6, 2))
50+
51+
| ({ kind: "c"; func?(): Partial<C> } & C)
52+
>kind : Symbol(kind, Decl(intraExpressionInferencesJsx.tsx, 20, 8))
53+
>func : Symbol(func, Decl(intraExpressionInferencesJsx.tsx, 20, 19))
54+
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
55+
>C : Symbol(C, Decl(intraExpressionInferencesJsx.tsx, 10, 2))
56+
>C : Symbol(C, Decl(intraExpressionInferencesJsx.tsx, 10, 2))
57+
58+
);
59+
};
60+
61+
type StyleParam<T extends Animations> = Record<keyof T, string>;
62+
>StyleParam : Symbol(StyleParam, Decl(intraExpressionInferencesJsx.tsx, 22, 2))
63+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 24, 16))
64+
>Animations : Symbol(Animations, Decl(intraExpressionInferencesJsx.tsx, 14, 2))
65+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
66+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 24, 16))
67+
68+
type AnimatedViewProps<T extends Animations> = {
69+
>AnimatedViewProps : Symbol(AnimatedViewProps, Decl(intraExpressionInferencesJsx.tsx, 24, 64))
70+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 26, 23))
71+
>Animations : Symbol(Animations, Decl(intraExpressionInferencesJsx.tsx, 14, 2))
72+
73+
style: (animationsValues: StyleParam<T>) => string;
74+
>style : Symbol(style, Decl(intraExpressionInferencesJsx.tsx, 26, 48))
75+
>animationsValues : Symbol(animationsValues, Decl(intraExpressionInferencesJsx.tsx, 27, 10))
76+
>StyleParam : Symbol(StyleParam, Decl(intraExpressionInferencesJsx.tsx, 22, 2))
77+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 26, 23))
78+
79+
animations: T;
80+
>animations : Symbol(animations, Decl(intraExpressionInferencesJsx.tsx, 27, 53))
81+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 26, 23))
82+
83+
};
84+
85+
const Component = <T extends Animations>({
86+
>Component : Symbol(Component, Decl(intraExpressionInferencesJsx.tsx, 31, 5))
87+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 31, 19))
88+
>Animations : Symbol(Animations, Decl(intraExpressionInferencesJsx.tsx, 14, 2))
89+
90+
animations,
91+
>animations : Symbol(animations, Decl(intraExpressionInferencesJsx.tsx, 31, 42))
92+
93+
style,
94+
>style : Symbol(style, Decl(intraExpressionInferencesJsx.tsx, 32, 13))
95+
96+
}: AnimatedViewProps<T>) => <></>;
97+
>AnimatedViewProps : Symbol(AnimatedViewProps, Decl(intraExpressionInferencesJsx.tsx, 24, 64))
98+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 31, 19))
99+
100+
<Component
101+
>Component : Symbol(Component, Decl(intraExpressionInferencesJsx.tsx, 31, 5))
102+
103+
animations={{
104+
>animations : Symbol(animations, Decl(intraExpressionInferencesJsx.tsx, 36, 10))
105+
106+
test: {
107+
>test : Symbol(test, Decl(intraExpressionInferencesJsx.tsx, 37, 15))
108+
109+
kind: "a",
110+
>kind : Symbol(kind, Decl(intraExpressionInferencesJsx.tsx, 38, 11))
111+
112+
value: 1,
113+
>value : Symbol(value, Decl(intraExpressionInferencesJsx.tsx, 39, 16))
114+
115+
a: true,
116+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 40, 15))
117+
118+
},
119+
}}
120+
style={(anim) => {
121+
>style : Symbol(style, Decl(intraExpressionInferencesJsx.tsx, 43, 4))
122+
>anim : Symbol(anim, Decl(intraExpressionInferencesJsx.tsx, 44, 10))
123+
124+
return "";
125+
}}
126+
/>;
127+
<Component
128+
>Component : Symbol(Component, Decl(intraExpressionInferencesJsx.tsx, 31, 5))
129+
130+
animations={{
131+
>animations : Symbol(animations, Decl(intraExpressionInferencesJsx.tsx, 48, 10))
132+
133+
test: {
134+
>test : Symbol(test, Decl(intraExpressionInferencesJsx.tsx, 49, 15))
135+
136+
kind: "a",
137+
>kind : Symbol(kind, Decl(intraExpressionInferencesJsx.tsx, 50, 11))
138+
139+
value: 1,
140+
>value : Symbol(value, Decl(intraExpressionInferencesJsx.tsx, 51, 16))
141+
142+
a: true,
143+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 52, 15))
144+
145+
func() {
146+
>func : Symbol(func, Decl(intraExpressionInferencesJsx.tsx, 53, 14))
147+
148+
return {
149+
a: true,
150+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 55, 16))
151+
152+
};
153+
},
154+
},
155+
}}
156+
style={(anim) => {
157+
>style : Symbol(style, Decl(intraExpressionInferencesJsx.tsx, 60, 4))
158+
>anim : Symbol(anim, Decl(intraExpressionInferencesJsx.tsx, 61, 10))
159+
160+
return "";
161+
}}
162+
/>;
163+
<Component
164+
>Component : Symbol(Component, Decl(intraExpressionInferencesJsx.tsx, 31, 5))
165+
166+
animations={{
167+
>animations : Symbol(animations, Decl(intraExpressionInferencesJsx.tsx, 65, 10))
168+
169+
test: {
170+
>test : Symbol(test, Decl(intraExpressionInferencesJsx.tsx, 66, 15))
171+
172+
kind: "a",
173+
>kind : Symbol(kind, Decl(intraExpressionInferencesJsx.tsx, 67, 11))
174+
175+
value: 1,
176+
>value : Symbol(value, Decl(intraExpressionInferencesJsx.tsx, 68, 16))
177+
178+
a: true,
179+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 69, 15))
180+
181+
func: () => {
182+
>func : Symbol(func, Decl(intraExpressionInferencesJsx.tsx, 70, 14))
183+
184+
return {
185+
a: true,
186+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 72, 16))
187+
188+
};
189+
},
190+
},
191+
}}
192+
style={(anim) => {
193+
>style : Symbol(style, Decl(intraExpressionInferencesJsx.tsx, 77, 4))
194+
>anim : Symbol(anim, Decl(intraExpressionInferencesJsx.tsx, 78, 10))
195+
196+
return "";
197+
}}
198+
/>;
199+
200+
// repro from #52786
201+
202+
interface Props<T> {
203+
>Props : Symbol(Props, Decl(intraExpressionInferencesJsx.tsx, 81, 3))
204+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 85, 16))
205+
206+
a: (x: string) => T;
207+
>a : Symbol(Props.a, Decl(intraExpressionInferencesJsx.tsx, 85, 20))
208+
>x : Symbol(x, Decl(intraExpressionInferencesJsx.tsx, 86, 6))
209+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 85, 16))
210+
211+
b: (arg: T) => void;
212+
>b : Symbol(Props.b, Decl(intraExpressionInferencesJsx.tsx, 86, 22))
213+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 87, 6))
214+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 85, 16))
215+
}
216+
217+
function Foo<T>(props: Props<T>) {
218+
>Foo : Symbol(Foo, Decl(intraExpressionInferencesJsx.tsx, 88, 1))
219+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 90, 13))
220+
>props : Symbol(props, Decl(intraExpressionInferencesJsx.tsx, 90, 16))
221+
>Props : Symbol(Props, Decl(intraExpressionInferencesJsx.tsx, 81, 3))
222+
>T : Symbol(T, Decl(intraExpressionInferencesJsx.tsx, 90, 13))
223+
224+
return <div />;
225+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
226+
}
227+
228+
<Foo
229+
>Foo : Symbol(Foo, Decl(intraExpressionInferencesJsx.tsx, 88, 1))
230+
231+
a={() => 10}
232+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 94, 4))
233+
234+
b={(arg) => { arg.toString(); }}
235+
>b : Symbol(b, Decl(intraExpressionInferencesJsx.tsx, 95, 14))
236+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 96, 6))
237+
>arg.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
238+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 96, 6))
239+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
240+
241+
/>;
242+
243+
<Foo
244+
>Foo : Symbol(Foo, Decl(intraExpressionInferencesJsx.tsx, 88, 1))
245+
246+
a={(x) => 10}
247+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 99, 4))
248+
>x : Symbol(x, Decl(intraExpressionInferencesJsx.tsx, 100, 6))
249+
250+
b={(arg) => { arg.toString(); }}
251+
>b : Symbol(b, Decl(intraExpressionInferencesJsx.tsx, 100, 15))
252+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 101, 6))
253+
>arg.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
254+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 101, 6))
255+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
256+
257+
/>;
258+
259+
<Foo {...{
260+
>Foo : Symbol(Foo, Decl(intraExpressionInferencesJsx.tsx, 88, 1))
261+
262+
a: (x) => 10,
263+
>a : Symbol(a, Decl(intraExpressionInferencesJsx.tsx, 104, 10))
264+
>x : Symbol(x, Decl(intraExpressionInferencesJsx.tsx, 105, 6))
265+
266+
b: (arg) => { arg.toString(); },
267+
>b : Symbol(b, Decl(intraExpressionInferencesJsx.tsx, 105, 15))
268+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 106, 6))
269+
>arg.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
270+
>arg : Symbol(arg, Decl(intraExpressionInferencesJsx.tsx, 106, 6))
271+
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
272+
273+
}} />;
274+

0 commit comments

Comments
 (0)