Skip to content

Commit 7b5ef64

Browse files
authored
Unify JSX And Normal Call Checking Codepaths (#27627)
* Unify JSX Call Checking Codepaths * Add tests for fixed issues * Fix lint, move all error checking into the only-run-once resolveSignature call * Remove unused (unreachable?) code path * Consolidate a little more duplicated logic into signature checking * Fix #19775 a bit more * Cosmetic changes from CR
1 parent eb2297d commit 7b5ef64

File tree

75 files changed

+1240
-1022
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+1240
-1022
lines changed

src/compiler/checker.ts

Lines changed: 223 additions & 564 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3103,8 +3103,6 @@ namespace ts {
31033103
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
31043104
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
31053105
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
3106-
3107-
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
31083106
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
31093107
isOptionalParameter(node: ParameterDeclaration): boolean;
31103108
getAmbientModules(): Symbol[];
@@ -3171,7 +3169,7 @@ namespace ts {
31713169
* True if `contextualType` should not be considered for completions because
31723170
* e.g. it specifies `kind: "a"` and obj has `kind: "b"`.
31733171
*/
3174-
/* @internal */ isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression): boolean;
3172+
/* @internal */ isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean;
31753173
/**
31763174
* For a union, will include a property if it's defined in *any* of the member types.
31773175
* So for `{ a } | { b }`, this will include both `a` and `b`.
@@ -3769,7 +3767,6 @@ namespace ts {
37693767
resolvedType?: Type; // Cached type of type node
37703768
resolvedEnumType?: Type; // Cached constraint type from enum jsdoc tag
37713769
resolvedSignature?: Signature; // Cached signature of signature node or call expression
3772-
resolvedSignatures?: Map<Signature[]>; // Cached signatures of jsx node
37733770
resolvedSymbol?: Symbol; // Cached name resolution result
37743771
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
37753772
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate

src/services/completions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,9 +1200,9 @@ namespace ts.Completions {
12001200
function tryGetJsxCompletionSymbols(): GlobalsSearch {
12011201
const jsxContainer = tryGetContainingJsxElement(contextToken);
12021202
// Cursor is inside a JSX self-closing element or opening element
1203-
const attrsType = jsxContainer && typeChecker.getAllAttributesTypeFromJsxOpeningLikeElement(jsxContainer);
1203+
const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
12041204
if (!attrsType) return GlobalsSearch.Continue;
1205-
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), jsxContainer!.attributes.properties);
1205+
symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties);
12061206
completionKind = CompletionKind.MemberLike;
12071207
isNewIdentifierLocation = false;
12081208
return GlobalsSearch.Success;
@@ -2211,7 +2211,7 @@ namespace ts.Completions {
22112211
return jsdoc && jsdoc.tags && (rangeContainsPosition(jsdoc, position) ? findLast(jsdoc.tags, tag => tag.pos < position) : undefined);
22122212
}
22132213

2214-
function getPropertiesForObjectExpression(contextualType: Type, obj: ObjectLiteralExpression, checker: TypeChecker): Symbol[] {
2214+
function getPropertiesForObjectExpression(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] {
22152215
return contextualType.isUnion()
22162216
? checker.getAllPossiblePropertiesOfTypes(contextualType.types.filter(memberType =>
22172217
// If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals.

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1941,7 +1941,6 @@ declare namespace ts {
19411941
/** Follow all aliases to get the original symbol. */
19421942
getAliasedSymbol(symbol: Symbol): Symbol;
19431943
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
1944-
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
19451944
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
19461945
isOptionalParameter(node: ParameterDeclaration): boolean;
19471946
getAmbientModules(): Symbol[];

tests/baselines/reference/api/typescript.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1941,7 +1941,6 @@ declare namespace ts {
19411941
/** Follow all aliases to get the original symbol. */
19421942
getAliasedSymbol(symbol: Symbol): Symbol;
19431943
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
1944-
getAllAttributesTypeFromJsxOpeningLikeElement(elementNode: JsxOpeningLikeElement): Type | undefined;
19451944
getJsxIntrinsicTagNamesAt(location: Node): Symbol[];
19461945
isOptionalParameter(node: ParameterDeclaration): boolean;
19471946
getAmbientModules(): Symbol[];

tests/baselines/reference/checkJsxChildrenProperty14.errors.txt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
tests/cases/conformance/jsx/file.tsx(42,11): error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'SingleChildProp'.
2-
Types of property 'children' are incompatible.
3-
Type 'Element[]' is not assignable to type 'Element'.
4-
Property 'type' is missing in type 'Element[]'.
1+
tests/cases/conformance/jsx/file.tsx(42,11): error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & SingleChildProp'.
2+
Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'SingleChildProp'.
3+
Types of property 'children' are incompatible.
4+
Type 'Element[]' is not assignable to type 'Element'.
5+
Property 'type' is missing in type 'Element[]'.
56

67

78
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
@@ -48,7 +49,8 @@ tests/cases/conformance/jsx/file.tsx(42,11): error TS2322: Type '{ children: Ele
4849
// Error
4950
let k5 = <SingleChildComp a={10} b="hi"><></><Button /><AnotherButton /></SingleChildComp>;
5051
~~~~~~~~~~~~~~~
51-
!!! error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'SingleChildProp'.
52-
!!! error TS2322: Types of property 'children' are incompatible.
53-
!!! error TS2322: Type 'Element[]' is not assignable to type 'Element'.
54-
!!! error TS2322: Property 'type' is missing in type 'Element[]'.
52+
!!! error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & SingleChildProp'.
53+
!!! error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'SingleChildProp'.
54+
!!! error TS2322: Types of property 'children' are incompatible.
55+
!!! error TS2322: Type 'Element[]' is not assignable to type 'Element'.
56+
!!! error TS2322: Property 'type' is missing in type 'Element[]'.
Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1-
tests/cases/conformance/jsx/file.tsx(14,10): error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'Prop'.
2-
Property 'children' is missing in type '{ a: number; b: string; }'.
1+
tests/cases/conformance/jsx/file.tsx(14,10): error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
2+
Type '{ a: number; b: string; }' is not assignable to type 'Prop'.
3+
Property 'children' is missing in type '{ a: number; b: string; }'.
34
tests/cases/conformance/jsx/file.tsx(17,11): error TS2710: 'children' are specified twice. The attribute named 'children' will be overwritten.
4-
tests/cases/conformance/jsx/file.tsx(31,6): error TS2322: Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'Prop'.
5-
Types of property 'children' are incompatible.
6-
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'string | Element'.
7-
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'Element'.
8-
Property 'type' is missing in type '(Element | ((name: string) => Element))[]'.
9-
tests/cases/conformance/jsx/file.tsx(37,6): error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
10-
Types of property 'children' are incompatible.
11-
Type '(number | Element)[]' is not assignable to type 'string | Element'.
12-
Type '(number | Element)[]' is not assignable to type 'Element'.
13-
Property 'type' is missing in type '(number | Element)[]'.
14-
tests/cases/conformance/jsx/file.tsx(43,6): error TS2322: Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
15-
Types of property 'children' are incompatible.
16-
Type '(string | Element)[]' is not assignable to type 'string | Element'.
17-
Type '(string | Element)[]' is not assignable to type 'Element'.
18-
Property 'type' is missing in type '(string | Element)[]'.
19-
tests/cases/conformance/jsx/file.tsx(49,6): error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'Prop'.
20-
Types of property 'children' are incompatible.
21-
Type 'Element[]' is not assignable to type 'string | Element'.
22-
Type 'Element[]' is not assignable to type 'Element'.
23-
Property 'type' is missing in type 'Element[]'.
5+
tests/cases/conformance/jsx/file.tsx(31,6): error TS2322: Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
6+
Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'Prop'.
7+
Types of property 'children' are incompatible.
8+
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'string | Element'.
9+
Type '(Element | ((name: string) => Element))[]' is not assignable to type 'Element'.
10+
Property 'type' is missing in type '(Element | ((name: string) => Element))[]'.
11+
tests/cases/conformance/jsx/file.tsx(37,6): error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
12+
Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
13+
Types of property 'children' are incompatible.
14+
Type '(number | Element)[]' is not assignable to type 'string | Element'.
15+
Type '(number | Element)[]' is not assignable to type 'Element'.
16+
Property 'type' is missing in type '(number | Element)[]'.
17+
tests/cases/conformance/jsx/file.tsx(43,6): error TS2322: Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
18+
Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
19+
Types of property 'children' are incompatible.
20+
Type '(string | Element)[]' is not assignable to type 'string | Element'.
21+
Type '(string | Element)[]' is not assignable to type 'Element'.
22+
Property 'type' is missing in type '(string | Element)[]'.
23+
tests/cases/conformance/jsx/file.tsx(49,6): error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
24+
Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'Prop'.
25+
Types of property 'children' are incompatible.
26+
Type 'Element[]' is not assignable to type 'string | Element'.
27+
Type 'Element[]' is not assignable to type 'Element'.
28+
Property 'type' is missing in type 'Element[]'.
2429

2530

2631
==== tests/cases/conformance/jsx/file.tsx (6 errors) ====
@@ -39,8 +44,9 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2322: Type '{ children: Elem
3944
// Error: missing children
4045
let k = <Comp a={10} b="hi" />;
4146
~~~~
42-
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'Prop'.
43-
!!! error TS2322: Property 'children' is missing in type '{ a: number; b: string; }'.
47+
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
48+
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'Prop'.
49+
!!! error TS2322: Property 'children' is missing in type '{ a: number; b: string; }'.
4450

4551
let k0 =
4652
<Comp a={10} b="hi" children="Random" >
@@ -61,47 +67,51 @@ tests/cases/conformance/jsx/file.tsx(49,6): error TS2322: Type '{ children: Elem
6167
let k2 =
6268
<Comp a={10} b="hi">
6369
~~~~
64-
!!! error TS2322: Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'Prop'.
65-
!!! error TS2322: Types of property 'children' are incompatible.
66-
!!! error TS2322: Type '(Element | ((name: string) => Element))[]' is not assignable to type 'string | Element'.
67-
!!! error TS2322: Type '(Element | ((name: string) => Element))[]' is not assignable to type 'Element'.
68-
!!! error TS2322: Property 'type' is missing in type '(Element | ((name: string) => Element))[]'.
70+
!!! error TS2322: Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
71+
!!! error TS2322: Type '{ children: (Element | ((name: string) => Element))[]; a: number; b: string; }' is not assignable to type 'Prop'.
72+
!!! error TS2322: Types of property 'children' are incompatible.
73+
!!! error TS2322: Type '(Element | ((name: string) => Element))[]' is not assignable to type 'string | Element'.
74+
!!! error TS2322: Type '(Element | ((name: string) => Element))[]' is not assignable to type 'Element'.
75+
!!! error TS2322: Property 'type' is missing in type '(Element | ((name: string) => Element))[]'.
6976
<div> My Div </div>
7077
{(name: string) => <div> My name {name} </div>}
7178
</Comp>;
7279

7380
let k3 =
7481
<Comp a={10} b="hi">
7582
~~~~
76-
!!! error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
77-
!!! error TS2322: Types of property 'children' are incompatible.
78-
!!! error TS2322: Type '(number | Element)[]' is not assignable to type 'string | Element'.
79-
!!! error TS2322: Type '(number | Element)[]' is not assignable to type 'Element'.
80-
!!! error TS2322: Property 'type' is missing in type '(number | Element)[]'.
83+
!!! error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
84+
!!! error TS2322: Type '{ children: (number | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
85+
!!! error TS2322: Types of property 'children' are incompatible.
86+
!!! error TS2322: Type '(number | Element)[]' is not assignable to type 'string | Element'.
87+
!!! error TS2322: Type '(number | Element)[]' is not assignable to type 'Element'.
88+
!!! error TS2322: Property 'type' is missing in type '(number | Element)[]'.
8189
<div> My Div </div>
8290
{1000000}
8391
</Comp>;
8492

8593
let k4 =
8694
<Comp a={10} b="hi" >
8795
~~~~
88-
!!! error TS2322: Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
89-
!!! error TS2322: Types of property 'children' are incompatible.
90-
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'string | Element'.
91-
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'Element'.
92-
!!! error TS2322: Property 'type' is missing in type '(string | Element)[]'.
96+
!!! error TS2322: Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
97+
!!! error TS2322: Type '{ children: (string | Element)[]; a: number; b: string; }' is not assignable to type 'Prop'.
98+
!!! error TS2322: Types of property 'children' are incompatible.
99+
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'string | Element'.
100+
!!! error TS2322: Type '(string | Element)[]' is not assignable to type 'Element'.
101+
!!! error TS2322: Property 'type' is missing in type '(string | Element)[]'.
93102
<div> My Div </div>
94103
hi hi hi!
95104
</Comp>;
96105

97106
let k5 =
98107
<Comp a={10} b="hi" >
99108
~~~~
100-
!!! error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'Prop'.
101-
!!! error TS2322: Types of property 'children' are incompatible.
102-
!!! error TS2322: Type 'Element[]' is not assignable to type 'string | Element'.
103-
!!! error TS2322: Type 'Element[]' is not assignable to type 'Element'.
104-
!!! error TS2322: Property 'type' is missing in type 'Element[]'.
109+
!!! error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & Prop'.
110+
!!! error TS2322: Type '{ children: Element[]; a: number; b: string; }' is not assignable to type 'Prop'.
111+
!!! error TS2322: Types of property 'children' are incompatible.
112+
!!! error TS2322: Type 'Element[]' is not assignable to type 'string | Element'.
113+
!!! error TS2322: Type 'Element[]' is not assignable to type 'Element'.
114+
!!! error TS2322: Property 'type' is missing in type 'Element[]'.
105115
<div> My Div </div>
106116
<div> My Div </div>
107117
</Comp>;

0 commit comments

Comments
 (0)