Skip to content

Commit

Permalink
Add errors when providing type arguments for intrinsic JSX tags (#40293)
Browse files Browse the repository at this point in the history
  • Loading branch information
weswigham committed Sep 8, 2020
1 parent cea1cfb commit 7838b01
Show file tree
Hide file tree
Showing 6 changed files with 321 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/compiler/checker.ts
Expand Up @@ -24280,7 +24280,6 @@ namespace ts {

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

function checkJsxSelfClosingElement(node: JsxSelfClosingElement, _checkMode: CheckMode | undefined): Type {
Expand Down Expand Up @@ -27469,6 +27468,10 @@ namespace ts {
const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
const fakeSignature = createSignatureForJSXIntrinsic(node, result);
checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes);
if (length(node.typeArguments)) {
forEach(node.typeArguments, checkSourceElement);
diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), node.typeArguments!, Diagnostics.Expected_0_type_arguments_but_got_1, 0, length(node.typeArguments)));
}
return fakeSignature;
}
const exprTypes = checkExpression(node.tagName);
Expand Down
@@ -0,0 +1,102 @@
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(5,15): error TS1099: Type argument list cannot be empty.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(7,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(7,22): error TS1009: Trailing comma not allowed.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(9,16): error TS2304: Cannot find name 'Missing'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(9,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(11,16): error TS2304: Cannot find name 'Missing'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(11,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(11,24): error TS2304: Cannot find name 'AlsoMissing'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(13,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(13,23): error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
Type 'object' is not assignable to type 'symbol'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(15,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(18,15): error TS1099: Type argument list cannot be empty.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(20,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(20,22): error TS1009: Trailing comma not allowed.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(22,16): error TS2304: Cannot find name 'Missing'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(22,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(24,16): error TS2304: Cannot find name 'Missing'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(24,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(24,24): error TS2304: Cannot find name 'AlsoMissing'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(26,16): error TS2558: Expected 0 type arguments, but got 1.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(26,23): error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
Type 'object' is not assignable to type 'symbol'.
tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx(28,16): error TS2558: Expected 0 type arguments, but got 1.


==== tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx (22 errors) ====
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";

// opening + closing
const a = <div<>></div>; // empty type args
~~
!!! error TS1099: Type argument list cannot be empty.

const b = <div<number,>></div>; // trailing comma type args
~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
~
!!! error TS1009: Trailing comma not allowed.

const c = <div<Missing>></div>; // nonexistant type args
~~~~~~~
!!! error TS2304: Cannot find name 'Missing'.
~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.

const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
~~~~~~~
!!! error TS2304: Cannot find name 'Missing'.
~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
~~~~~~~~~~~
!!! error TS2304: Cannot find name 'AlsoMissing'.

const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
~~~~~~
!!! error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
!!! error TS2344: Type 'object' is not assignable to type 'symbol'.

const f = <div<number>></div>; // existing type argument with no internal issues
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.

// self-closing
const g = <div<>/>; // empty type args
~~
!!! error TS1099: Type argument list cannot be empty.

const h = <div<number,>/>; // trailing comma type args
~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
~
!!! error TS1009: Trailing comma not allowed.

const i = <div<Missing>/>; // nonexistant type args
~~~~~~~
!!! error TS2304: Cannot find name 'Missing'.
~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.

const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
~~~~~~~
!!! error TS2304: Cannot find name 'Missing'.
~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
~~~~~~~~~~~
!!! error TS2304: Cannot find name 'AlsoMissing'.

const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.
~~~~~~
!!! error TS2344: Type 'object' does not satisfy the constraint 'string | number | symbol'.
!!! error TS2344: Type 'object' is not assignable to type 'symbol'.

const l = <div<number>/>; // existing type argument with no internal issues
~~~~~~
!!! error TS2558: Expected 0 type arguments, but got 1.

@@ -0,0 +1,50 @@
//// [jsxIntrinsicElementsTypeArgumentErrors.tsx]
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";

// opening + closing
const a = <div<>></div>; // empty type args

const b = <div<number,>></div>; // trailing comma type args

const c = <div<Missing>></div>; // nonexistant type args

const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args

const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args

const f = <div<number>></div>; // existing type argument with no internal issues

// self-closing
const g = <div<>/>; // empty type args

const h = <div<number,>/>; // trailing comma type args

const i = <div<Missing>/>; // nonexistant type args

const j = <div<Missing<AlsoMissing>>/>; // nested missing type args

const k = <div<Record<object, object>>/>; // existing but incorrect nested type args

const l = <div<number>/>; // existing type argument with no internal issues


//// [jsxIntrinsicElementsTypeArgumentErrors.js]
"use strict";
exports.__esModule = true;
/// <reference path="react16.d.ts" />
var React = require("react");
// opening + closing
var a = React.createElement("div", null); // empty type args
var b = React.createElement("div", null); // trailing comma type args
var c = React.createElement("div", null); // nonexistant type args
var d = React.createElement("div", null); // nested missing type args
var e = React.createElement("div", null); // existing but incorrect nested type args
var f = React.createElement("div", null); // existing type argument with no internal issues
// self-closing
var g = React.createElement("div", null); // empty type args
var h = React.createElement("div", null); // trailing comma type args
var i = React.createElement("div", null); // nonexistant type args
var j = React.createElement("div", null); // nested missing type args
var k = React.createElement("div", null); // existing but incorrect nested type args
var l = React.createElement("div", null); // existing type argument with no internal issues
@@ -0,0 +1,63 @@
=== tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx ===
/// <reference path="react16.d.ts" />
import * as React from "react";
>React : Symbol(React, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 1, 6))

// opening + closing
const a = <div<>></div>; // empty type args
>a : Symbol(a, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 4, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const b = <div<number,>></div>; // trailing comma type args
>b : Symbol(b, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 6, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const c = <div<Missing>></div>; // nonexistant type args
>c : Symbol(c, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 8, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
>d : Symbol(d, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 10, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
>e : Symbol(e, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 12, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const f = <div<number>></div>; // existing type argument with no internal issues
>f : Symbol(f, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 14, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

// self-closing
const g = <div<>/>; // empty type args
>g : Symbol(g, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 17, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const h = <div<number,>/>; // trailing comma type args
>h : Symbol(h, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 19, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const i = <div<Missing>/>; // nonexistant type args
>i : Symbol(i, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 21, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
>j : Symbol(j, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 23, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
>k : Symbol(k, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 25, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))

const l = <div<number>/>; // existing type argument with no internal issues
>l : Symbol(l, Decl(jsxIntrinsicElementsTypeArgumentErrors.tsx, 27, 5))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))

@@ -0,0 +1,73 @@
=== tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx ===
/// <reference path="react16.d.ts" />
import * as React from "react";
>React : typeof React

// opening + closing
const a = <div<>></div>; // empty type args
>a : JSX.Element
><div<>></div> : JSX.Element
>div : any
>div : any

const b = <div<number,>></div>; // trailing comma type args
>b : JSX.Element
><div<number,>></div> : JSX.Element
>div : any
>div : any

const c = <div<Missing>></div>; // nonexistant type args
>c : JSX.Element
><div<Missing>></div> : JSX.Element
>div : any
>div : any

const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args
>d : JSX.Element
><div<Missing<AlsoMissing>>></div> : JSX.Element
>div : any
>div : any

const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args
>e : JSX.Element
><div<Record<object, object>>></div> : JSX.Element
>div : any
>div : any

const f = <div<number>></div>; // existing type argument with no internal issues
>f : JSX.Element
><div<number>></div> : JSX.Element
>div : any
>div : any

// self-closing
const g = <div<>/>; // empty type args
>g : JSX.Element
><div<>/> : JSX.Element
>div : any

const h = <div<number,>/>; // trailing comma type args
>h : JSX.Element
><div<number,>/> : JSX.Element
>div : any

const i = <div<Missing>/>; // nonexistant type args
>i : JSX.Element
><div<Missing>/> : JSX.Element
>div : any

const j = <div<Missing<AlsoMissing>>/>; // nested missing type args
>j : JSX.Element
><div<Missing<AlsoMissing>>/> : JSX.Element
>div : any

const k = <div<Record<object, object>>/>; // existing but incorrect nested type args
>k : JSX.Element
><div<Record<object, object>>/> : JSX.Element
>div : any

const l = <div<number>/>; // existing type argument with no internal issues
>l : JSX.Element
><div<number>/> : JSX.Element
>div : any

29 changes: 29 additions & 0 deletions tests/cases/compiler/jsxIntrinsicElementsTypeArgumentErrors.tsx
@@ -0,0 +1,29 @@
// @jsx: react
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";

// opening + closing
const a = <div<>></div>; // empty type args

const b = <div<number,>></div>; // trailing comma type args

const c = <div<Missing>></div>; // nonexistant type args

const d = <div<Missing<AlsoMissing>>></div>; // nested missing type args

const e = <div<Record<object, object>>></div>; // existing but incorrect nested type args

const f = <div<number>></div>; // existing type argument with no internal issues

// self-closing
const g = <div<>/>; // empty type args

const h = <div<number,>/>; // trailing comma type args

const i = <div<Missing>/>; // nonexistant type args

const j = <div<Missing<AlsoMissing>>/>; // nested missing type args

const k = <div<Record<object, object>>/>; // existing but incorrect nested type args

const l = <div<number>/>; // existing type argument with no internal issues

0 comments on commit 7838b01

Please sign in to comment.