Skip to content

Add errors when providing type arguments for intrinsic JSX tags #40293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24252,7 +24252,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 @@ -27441,6 +27440,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
Original file line number Diff line number Diff line change
@@ -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.

Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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))

Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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