Skip to content

Commit aadadb4

Browse files
committed
Add errors when providing type arguments for intrinsic JSX tags
1 parent 27eb862 commit aadadb4

6 files changed

+321
-1
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24252,7 +24252,6 @@ namespace ts {
2425224252

2425324253
function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) {
2425424254
checkJsxOpeningLikeElementOrOpeningFragment(node);
24255-
resolveUntypedCall(node); // ensure type arguments and parameters are typechecked, even if there is an arity error
2425624255
}
2425724256

2425824257
function checkJsxSelfClosingElement(node: JsxSelfClosingElement, _checkMode: CheckMode | undefined): Type {
@@ -27441,6 +27440,10 @@ namespace ts {
2744127440
const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
2744227441
const fakeSignature = createSignatureForJSXIntrinsic(node, result);
2744327442
checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes);
27443+
if (length(node.typeArguments)) {
27444+
forEach(node.typeArguments, checkSourceElement);
27445+
diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), node.typeArguments!, Diagnostics.Expected_0_type_arguments_but_got_1, 0, length(node.typeArguments)));
27446+
}
2744427447
return fakeSignature;
2744527448
}
2744627449
const exprTypes = checkExpression(node.tagName);
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(5,15): error TS1099: Type argument list cannot be empty.
2+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(7,16): error TS2558: Expected 0 type arguments, but got 1.
3+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(7,22): error TS1009: Trailing comma not allowed.
4+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(9,16): error TS2304: Cannot find name 'Missing'.
5+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(9,16): error TS2558: Expected 0 type arguments, but got 1.
6+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(11,16): error TS2304: Cannot find name 'Missing'.
7+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(11,16): error TS2558: Expected 0 type arguments, but got 1.
8+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(11,24): error TS2304: Cannot find name 'AlsoMissing'.
9+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(13,16): error TS2558: Expected 0 type arguments, but got 1.
10+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(13,23): error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
11+
Type 'object' is not assignable to type 'symbol'.
12+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(15,16): error TS2558: Expected 0 type arguments, but got 1.
13+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(18,15): error TS1099: Type argument list cannot be empty.
14+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(20,16): error TS2558: Expected 0 type arguments, but got 1.
15+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(20,22): error TS1009: Trailing comma not allowed.
16+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(22,16): error TS2304: Cannot find name 'Missing'.
17+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(22,16): error TS2558: Expected 0 type arguments, but got 1.
18+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(24,16): error TS2304: Cannot find name 'Missing'.
19+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(24,16): error TS2558: Expected 0 type arguments, but got 1.
20+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(24,24): error TS2304: Cannot find name 'AlsoMissing'.
21+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(26,16): error TS2558: Expected 0 type arguments, but got 1.
22+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(26,23): error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
23+
Type 'object' is not assignable to type 'symbol'.
24+
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(28,16): error TS2558: Expected 0 type arguments, but got 1.
25+
26+
27+
==== tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx (22 errors) ====
28+
/// <reference path="/.lib/react16.d.ts" />
29+
import * as React from "react";
30+
31+
// opening + closing
32+
const a = <div<>></div>; // empty type args
33+
~~
34+
!!! error TS1099: Type argument list cannot be empty.
35+
36+
const b = <div<number,>></div>; // trailing comma type args
37+
~~~~~~~
38+
!!! error TS2558: Expected 0 type arguments, but got 1.
39+
~
40+
!!! error TS1009: Trailing comma not allowed.
41+
42+
const c = <div<Missing>></div>; // nonexistant type args
43+
~~~~~~~
44+
!!! error TS2304: Cannot find name 'Missing'.
45+
~~~~~~~
46+
!!! error TS2558: Expected 0 type arguments, but got 1.
47+
48+
const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
49+
~~~~~~~
50+
!!! error TS2304: Cannot find name 'Missing'.
51+
~~~~~~~~~~~~~~~~~~~~
52+
!!! error TS2558: Expected 0 type arguments, but got 1.
53+
~~~~~~~~~~~
54+
!!! error TS2304: Cannot find name 'AlsoMissing'.
55+
56+
const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
57+
~~~~~~~~~~~~~~~~~~~~~~
58+
!!! error TS2558: Expected 0 type arguments, but got 1.
59+
~~~~~~
60+
!!! error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
61+
!!! error TS2344: Type 'object' is not assignable to type 'symbol'.
62+
63+
const f = <div<number>></div>; // existing type argument with no internal issues
64+
~~~~~~
65+
!!! error TS2558: Expected 0 type arguments, but got 1.
66+
67+
// self-closing
68+
const g = <div<>/>; // empty type args
69+
~~
70+
!!! error TS1099: Type argument list cannot be empty.
71+
72+
const h = <div<number,>/>; // trailing comma type args
73+
~~~~~~~
74+
!!! error TS2558: Expected 0 type arguments, but got 1.
75+
~
76+
!!! error TS1009: Trailing comma not allowed.
77+
78+
const i = <div<Missing>/>; // nonexistant type args
79+
~~~~~~~
80+
!!! error TS2304: Cannot find name 'Missing'.
81+
~~~~~~~
82+
!!! error TS2558: Expected 0 type arguments, but got 1.
83+
84+
const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
85+
~~~~~~~
86+
!!! error TS2304: Cannot find name 'Missing'.
87+
~~~~~~~~~~~~~~~~~~~~
88+
!!! error TS2558: Expected 0 type arguments, but got 1.
89+
~~~~~~~~~~~
90+
!!! error TS2304: Cannot find name 'AlsoMissing'.
91+
92+
const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
93+
~~~~~~~~~~~~~~~~~~~~~~
94+
!!! error TS2558: Expected 0 type arguments, but got 1.
95+
~~~~~~
96+
!!! error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
97+
!!! error TS2344: Type 'object' is not assignable to type 'symbol'.
98+
99+
const l = <div<number>/>; // existing type argument with no internal issues
100+
~~~~~~
101+
!!! error TS2558: Expected 0 type arguments, but got 1.
102+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//// [jsxIntrinsicElementsTypeArgumentErrors.tsx]
2+
/// <reference path="/.lib/react16.d.ts" />
3+
import * as React from "react";
4+
5+
// opening + closing
6+
const a = <div<>></div>; // empty type args
7+
8+
const b = <div<number,>></div>; // trailing comma type args
9+
10+
const c = <div<Missing>></div>; // nonexistant type args
11+
12+
const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
13+
14+
const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
15+
16+
const f = <div<number>></div>; // existing type argument with no internal issues
17+
18+
// self-closing
19+
const g = <div<>/>; // empty type args
20+
21+
const h = <div<number,>/>; // trailing comma type args
22+
23+
const i = <div<Missing>/>; // nonexistant type args
24+
25+
const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
26+
27+
const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
28+
29+
const l = <div<number>/>; // existing type argument with no internal issues
30+
31+
32+
//// [jsxIntrinsicElementsTypeArgumentErrors.js]
33+
"use strict";
34+
exports.__esModule = true;
35+
/// <reference path="react16.d.ts" />
36+
var React = require("react");
37+
// opening + closing
38+
var a = React.createElement("div", null); // empty type args
39+
var b = React.createElement("div", null); // trailing comma type args
40+
var c = React.createElement("div", null); // nonexistant type args
41+
var d = React.createElement("div", null); // nested missing type args
42+
var e = React.createElement("div", null); // existing but incorrect nested type args
43+
var f = React.createElement("div", null); // existing type argument with no internal issues
44+
// self-closing
45+
var g = React.createElement("div", null); // empty type args
46+
var h = React.createElement("div", null); // trailing comma type args
47+
var i = React.createElement("div", null); // nonexistant type args
48+
var j = React.createElement("div", null); // nested missing type args
49+
var k = React.createElement("div", null); // existing but incorrect nested type args
50+
var l = React.createElement("div", null); // existing type argument with no internal issues
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx ===
2+
/// <reference path="react16.d.ts" />
3+
import * as React from "react";
4+
>React : Symbol(React, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 1, 6))
5+
6+
// opening + closing
7+
const a = <div<>></div>; // empty type args
8+
>a : Symbol(a, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 4, 5))
9+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
10+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
11+
12+
const b = <div<number,>></div>; // trailing comma type args
13+
>b : Symbol(b, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 6, 5))
14+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
15+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
16+
17+
const c = <div<Missing>></div>; // nonexistant type args
18+
>c : Symbol(c, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 8, 5))
19+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
20+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
21+
22+
const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
23+
>d : Symbol(d, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 10, 5))
24+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
25+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
26+
27+
const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
28+
>e : Symbol(e, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 12, 5))
29+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
30+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
31+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
32+
33+
const f = <div<number>></div>; // existing type argument with no internal issues
34+
>f : Symbol(f, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 14, 5))
35+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
36+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
37+
38+
// self-closing
39+
const g = <div<>/>; // empty type args
40+
>g : Symbol(g, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 17, 5))
41+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
42+
43+
const h = <div<number,>/>; // trailing comma type args
44+
>h : Symbol(h, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 19, 5))
45+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
46+
47+
const i = <div<Missing>/>; // nonexistant type args
48+
>i : Symbol(i, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 21, 5))
49+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
50+
51+
const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
52+
>j : Symbol(j, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 23, 5))
53+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
54+
55+
const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
56+
>k : Symbol(k, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 25, 5))
57+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
58+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
59+
60+
const l = <div<number>/>; // existing type argument with no internal issues
61+
>l : Symbol(l, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 27, 5))
62+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
63+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx ===
2+
/// <reference path="react16.d.ts" />
3+
import * as React from "react";
4+
>React : typeof React
5+
6+
// opening + closing
7+
const a = <div<>></div>; // empty type args
8+
>a : JSX.Element
9+
><div<>></div> : JSX.Element
10+
>div : any
11+
>div : any
12+
13+
const b = <div<number,>></div>; // trailing comma type args
14+
>b : JSX.Element
15+
><div<number,>></div> : JSX.Element
16+
>div : any
17+
>div : any
18+
19+
const c = <div<Missing>></div>; // nonexistant type args
20+
>c : JSX.Element
21+
><div<Missing>></div> : JSX.Element
22+
>div : any
23+
>div : any
24+
25+
const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
26+
>d : JSX.Element
27+
><div<Missing<AlsoMissing>>></div> : JSX.Element
28+
>div : any
29+
>div : any
30+
31+
const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
32+
>e : JSX.Element
33+
><div<Record<object, object>>></div> : JSX.Element
34+
>div : any
35+
>div : any
36+
37+
const f = <div<number>></div>; // existing type argument with no internal issues
38+
>f : JSX.Element
39+
><div<number>></div> : JSX.Element
40+
>div : any
41+
>div : any
42+
43+
// self-closing
44+
const g = <div<>/>; // empty type args
45+
>g : JSX.Element
46+
><div<>/> : JSX.Element
47+
>div : any
48+
49+
const h = <div<number,>/>; // trailing comma type args
50+
>h : JSX.Element
51+
><div<number,>/> : JSX.Element
52+
>div : any
53+
54+
const i = <div<Missing>/>; // nonexistant type args
55+
>i : JSX.Element
56+
><div<Missing>/> : JSX.Element
57+
>div : any
58+
59+
const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
60+
>j : JSX.Element
61+
><div<Missing<AlsoMissing>>/> : JSX.Element
62+
>div : any
63+
64+
const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
65+
>k : JSX.Element
66+
><div<Record<object, object>>/> : JSX.Element
67+
>div : any
68+
69+
const l = <div<number>/>; // existing type argument with no internal issues
70+
>l : JSX.Element
71+
><div<number>/> : JSX.Element
72+
>div : any
73+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// @jsx: react
2+
/// <reference path="/.lib/react16.d.ts" />
3+
import * as React from "react";
4+
5+
// opening + closing
6+
const a = <div<>></div>; // empty type args
7+
8+
const b = <div<number,>></div>; // trailing comma type args
9+
10+
const c = <div<Missing>></div>; // nonexistant type args
11+
12+
const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
13+
14+
const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
15+
16+
const f = <div<number>></div>; // existing type argument with no internal issues
17+
18+
// self-closing
19+
const g = <div<>/>; // empty type args
20+
21+
const h = <div<number,>/>; // trailing comma type args
22+
23+
const i = <div<Missing>/>; // nonexistant type args
24+
25+
const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
26+
27+
const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
28+
29+
const l = <div<number>/>; // existing type argument with no internal issues

0 commit comments

Comments
 (0)