Parse and check type arguments on JSX opening and self-closing tags (#22415)

* Parse and check type arguments on JSX opening like elements

* Fix nits
This commit is contained in:
Wesley Wigham
2018-03-22 15:07:36 -07:00
committed by GitHub
parent a7b066fe04
commit a909000b62
18 changed files with 985 additions and 34 deletions

View File

@@ -14660,7 +14660,7 @@ namespace ts {
return mapType(valueType, t => getJsxSignaturesParameterTypes(t, isJs, node));
}
function getJsxSignaturesParameterTypes(valueType: Type, isJs: boolean, context: Node) {
function getJsxSignaturesParameterTypes(valueType: Type, isJs: boolean, context: JsxOpeningLikeElement) {
// If the elemType is a string type, we have to return anyType to prevent an error downstream as we will try to find construct or call signature of the type
if (valueType.flags & TypeFlags.String) {
return anyType;
@@ -14698,6 +14698,10 @@ namespace ts {
}
}
if (context.typeArguments) {
signatures = mapDefined(signatures, s => getJsxSignatureTypeArgumentInstantiation(s, context, isJs));
}
return getUnionType(map(signatures, ctor ? t => getJsxPropsTypeFromConstructSignature(t, isJs, context) : t => getJsxPropsTypeFromCallSignature(t, context)), UnionReduction.None);
}
@@ -15508,21 +15512,57 @@ namespace ts {
// Instantiate in context of source type
const instantiatedSignatures = [];
let candidateForTypeArgumentError: Signature;
let hasTypeArgumentError: boolean = !!node.typeArguments;
for (const signature of signatures) {
if (signature.typeParameters) {
const isJavascript = isInJavaScriptFile(node);
const inferenceContext = createInferenceContext(signature.typeParameters, signature, /*flags*/ isJavascript ? InferenceFlags.AnyDefault : InferenceFlags.None);
const typeArguments = inferJsxTypeArguments(signature, node, inferenceContext);
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript));
const typeArgumentInstantiated = getJsxSignatureTypeArgumentInstantiation(signature, node, isJavascript, /*reportErrors*/ false);
if (typeArgumentInstantiated) {
hasTypeArgumentError = false;
instantiatedSignatures.push(typeArgumentInstantiated);
}
else {
if (node.typeArguments && hasCorrectTypeArgumentArity(signature, node.typeArguments)) {
candidateForTypeArgumentError = signature;
}
const inferenceContext = createInferenceContext(signature.typeParameters, signature, /*flags*/ isJavascript ? InferenceFlags.AnyDefault : InferenceFlags.None);
const typeArguments = inferJsxTypeArguments(signature, node, inferenceContext);
instantiatedSignatures.push(getSignatureInstantiation(signature, typeArguments, isJavascript));
}
}
else {
instantiatedSignatures.push(signature);
}
}
if (node.typeArguments && hasTypeArgumentError) {
if (candidateForTypeArgumentError) {
checkTypeArguments(candidateForTypeArgumentError, node.typeArguments, /*reportErrors*/ true);
}
// Length check to avoid issuing an arity error on length=0, the "Type argument list cannot be empty" grammar error alone is fine
else if (node.typeArguments.length !== 0) {
diagnostics.add(getTypeArgumentArityError(node, signatures, node.typeArguments));
}
}
return getUnionType(map(instantiatedSignatures, getReturnTypeOfSignature), UnionReduction.Subtype);
}
function getJsxSignatureTypeArgumentInstantiation(signature: Signature, node: JsxOpeningLikeElement, isJavascript: boolean, reportErrors?: boolean) {
if (!node.typeArguments) {
return;
}
if (!hasCorrectTypeArgumentArity(signature, node.typeArguments)) {
return;
}
const args = checkTypeArguments(signature, node.typeArguments, reportErrors);
if (!args) {
return;
}
return getSignatureInstantiation(signature, args, isJavascript);
}
function getJsxNamespaceAt(location: Node) {
const namespaceName = getJsxNamespace(location);
const resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false);
@@ -16784,13 +16824,7 @@ namespace ts {
spreadArgIndex = getSpreadArgumentIndex(args);
}
// If the user supplied type arguments, but the number of type arguments does not match
// the declared number of type parameters, the call has an incorrect arity.
const numTypeParameters = length(signature.typeParameters);
const minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters);
const hasRightNumberOfTypeArgs = !typeArguments ||
(typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters);
if (!hasRightNumberOfTypeArgs) {
if (!hasCorrectTypeArgumentArity(signature, typeArguments)) {
return false;
}
@@ -16810,6 +16844,15 @@ namespace ts {
return callIsIncomplete || hasEnoughArguments;
}
function hasCorrectTypeArgumentArity(signature: Signature, typeArguments: NodeArray<TypeNode> | undefined) {
// If the user supplied type arguments, but the number of type arguments does not match
// the declared number of type parameters, the call has an incorrect arity.
const numTypeParameters = length(signature.typeParameters);
const minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters);
return !typeArguments ||
(typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters);
}
// If type has a single call signature and no other members, return that signature. Otherwise, return undefined.
function getSingleCallSignature(type: Type): Signature {
if (type.flags & TypeFlags.Object) {
@@ -17371,6 +17414,17 @@ namespace ts {
}
}
function getTypeArgumentArityError(node: Node, signatures: Signature[], typeArguments: NodeArray<TypeNode>) {
let min = Infinity;
let max = -Infinity;
for (const sig of signatures) {
min = Math.min(min, getMinTypeArgumentCount(sig.typeParameters));
max = Math.max(max, length(sig.typeParameters));
}
const paramCount = min === max ? min : min + "-" + max;
return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length);
}
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], fallbackError?: DiagnosticMessage): Signature {
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
const isDecorator = node.kind === SyntaxKind.Decorator;
@@ -17498,14 +17552,7 @@ namespace ts {
checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression).typeArguments, /*reportErrors*/ true, fallbackError);
}
else if (typeArguments && every(signatures, sig => length(sig.typeParameters) !== typeArguments.length)) {
let min = Number.POSITIVE_INFINITY;
let max = Number.NEGATIVE_INFINITY;
for (const sig of signatures) {
min = Math.min(min, getMinTypeArgumentCount(sig.typeParameters));
max = Math.max(max, length(sig.typeParameters));
}
const paramCount = min < max ? min + "-" + max : min;
diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, paramCount, typeArguments.length));
diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments));
}
else if (args) {
let min = Number.POSITIVE_INFINITY;
@@ -26722,6 +26769,7 @@ namespace ts {
}
function checkGrammarJsxElement(node: JsxOpeningLikeElement) {
checkGrammarTypeArguments(node, node.typeArguments);
const seen = createUnderscoreEscapedMap<boolean>();
for (const attr of node.attributes.properties) {

View File

@@ -2160,31 +2160,35 @@ namespace ts {
: node;
}
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributes) {
export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
const node = <JsxSelfClosingElement>createSynthesizedNode(SyntaxKind.JsxSelfClosingElement);
node.tagName = tagName;
node.typeArguments = typeArguments && createNodeArray(typeArguments);
node.attributes = attributes;
return node;
}
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributes) {
export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
return node.tagName !== tagName
|| node.typeArguments !== typeArguments
|| node.attributes !== attributes
? updateNode(createJsxSelfClosingElement(tagName, attributes), node)
? updateNode(createJsxSelfClosingElement(tagName, typeArguments, attributes), node)
: node;
}
export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributes) {
export function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
const node = <JsxOpeningElement>createSynthesizedNode(SyntaxKind.JsxOpeningElement);
node.tagName = tagName;
node.typeArguments = typeArguments && createNodeArray(typeArguments);
node.attributes = attributes;
return node;
}
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributes) {
export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes) {
return node.tagName !== tagName
|| node.typeArguments !== typeArguments
|| node.attributes !== attributes
? updateNode(createJsxOpeningElement(tagName, attributes), node)
? updateNode(createJsxOpeningElement(tagName, typeArguments, attributes), node)
: node;
}

View File

@@ -429,6 +429,7 @@ namespace ts {
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
visitNodes(cbNode, cbNodes, (<JsxOpeningLikeElement>node).typeArguments) ||
visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
case SyntaxKind.JsxAttributes:
return visitNodes(cbNode, cbNodes, (<JsxAttributes>node).properties);
@@ -4197,6 +4198,7 @@ namespace ts {
}
const tagName = parseJsxElementName();
const typeArguments = tryParseTypeArguments();
const attributes = parseJsxAttributes();
let node: JsxOpeningLikeElement;
@@ -4221,6 +4223,7 @@ namespace ts {
}
node.tagName = tagName;
node.typeArguments = typeArguments;
node.attributes = attributes;
return finishNode(node);

View File

@@ -1458,8 +1458,10 @@ namespace ts {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
// Check type arguments
if (nodes === (<CallExpression | NewExpression | ExpressionWithTypeArguments>parent).typeArguments) {
if (nodes === (<CallExpression | NewExpression | ExpressionWithTypeArguments | JsxOpeningLikeElement>parent).typeArguments) {
diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.type_arguments_can_only_be_used_in_a_ts_file));
return;
}

View File

@@ -1768,6 +1768,7 @@ namespace ts {
kind: SyntaxKind.JsxOpeningElement;
parent?: JsxElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
}
@@ -1775,6 +1776,7 @@ namespace ts {
export interface JsxSelfClosingElement extends PrimaryExpression {
kind: SyntaxKind.JsxSelfClosingElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
}

View File

@@ -821,11 +821,13 @@ namespace ts {
case SyntaxKind.JsxSelfClosingElement:
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
visitNode((<JsxSelfClosingElement>node).tagName, visitor, isJsxTagNameExpression),
nodesVisitor((<JsxSelfClosingElement>node).typeArguments, visitor, isTypeNode),
visitNode((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributes));
case SyntaxKind.JsxOpeningElement:
return updateJsxOpeningElement(<JsxOpeningElement>node,
visitNode((<JsxOpeningElement>node).tagName, visitor, isJsxTagNameExpression),
nodesVisitor((<JsxSelfClosingElement>node).typeArguments, visitor, isTypeNode),
visitNode((<JsxOpeningElement>node).attributes, visitor, isJsxAttributes));
case SyntaxKind.JsxClosingElement:

View File

@@ -1081,11 +1081,13 @@ declare namespace ts {
kind: SyntaxKind.JsxOpeningElement;
parent?: JsxElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
}
interface JsxSelfClosingElement extends PrimaryExpression {
kind: SyntaxKind.JsxSelfClosingElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
}
interface JsxFragment extends PrimaryExpression {
@@ -3675,10 +3677,10 @@ declare namespace ts {
function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference;
function createJsxElement(openingElement: JsxOpeningElement, children: ReadonlyArray<JsxChild>, closingElement: JsxClosingElement): JsxElement;
function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: ReadonlyArray<JsxChild>, closingElement: JsxClosingElement): JsxElement;
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxSelfClosingElement;
function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxSelfClosingElement;
function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxOpeningElement;
function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxOpeningElement;
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxSelfClosingElement;
function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxSelfClosingElement;
function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxOpeningElement;
function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxOpeningElement;
function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement;
function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement;
function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray<JsxChild>, closingFragment: JsxClosingFragment): JsxFragment;

View File

@@ -1081,11 +1081,13 @@ declare namespace ts {
kind: SyntaxKind.JsxOpeningElement;
parent?: JsxElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
}
interface JsxSelfClosingElement extends PrimaryExpression {
kind: SyntaxKind.JsxSelfClosingElement;
tagName: JsxTagNameExpression;
typeArguments?: NodeArray<TypeNode>;
attributes: JsxAttributes;
}
interface JsxFragment extends PrimaryExpression {
@@ -3622,10 +3624,10 @@ declare namespace ts {
function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference;
function createJsxElement(openingElement: JsxOpeningElement, children: ReadonlyArray<JsxChild>, closingElement: JsxClosingElement): JsxElement;
function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: ReadonlyArray<JsxChild>, closingElement: JsxClosingElement): JsxElement;
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxSelfClosingElement;
function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxSelfClosingElement;
function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxOpeningElement;
function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributes): JsxOpeningElement;
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxSelfClosingElement;
function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxSelfClosingElement;
function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxOpeningElement;
function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: ReadonlyArray<TypeNode> | undefined, attributes: JsxAttributes): JsxOpeningElement;
function createJsxClosingElement(tagName: JsxTagNameExpression): JsxClosingElement;
function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression): JsxClosingElement;
function createJsxFragment(openingFragment: JsxOpeningFragment, children: ReadonlyArray<JsxChild>, closingFragment: JsxClosingFragment): JsxFragment;

View File

@@ -0,0 +1,22 @@
tests/cases/conformance/jsx/file.jsx(4,17): error TS8011: 'type arguments' can only be used in a .ts file.
==== tests/cases/conformance/jsx/component.d.ts (0 errors) ====
import * as React from "react";
export declare class MyComp<P> extends React.Component<P, {}> {
internalProp: P;
}
export interface Prop {
a: number,
b: string
}
==== tests/cases/conformance/jsx/file.jsx (1 errors) ====
import { MyComp, Prop } from "./component";
import * as React from "react";
let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
~~~~
!!! error TS8011: 'type arguments' can only be used in a .ts file.

View File

@@ -0,0 +1,26 @@
//// [tests/cases/conformance/jsx/jsxCheckJsxNoTypeArgumentsAllowed.tsx] ////
//// [component.d.ts]
import * as React from "react";
export declare class MyComp<P> extends React.Component<P, {}> {
internalProp: P;
}
export interface Prop {
a: number,
b: string
}
//// [file.jsx]
import { MyComp, Prop } from "./component";
import * as React from "react";
let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
//// [file.jsx]
"use strict";
exports.__esModule = true;
var component_1 = require("./component");
var React = require("react");
var x = <component_1.MyComp a={10} b="hi"/>; // error, no type arguments in js

View File

@@ -0,0 +1,42 @@
=== tests/cases/conformance/jsx/component.d.ts ===
import * as React from "react";
>React : Symbol(React, Decl(component.d.ts, 0, 6))
export declare class MyComp<P> extends React.Component<P, {}> {
>MyComp : Symbol(MyComp, Decl(component.d.ts, 0, 31))
>P : Symbol(P, Decl(component.d.ts, 1, 28))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>React : Symbol(React, Decl(component.d.ts, 0, 6))
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>P : Symbol(P, Decl(component.d.ts, 1, 28))
internalProp: P;
>internalProp : Symbol(MyComp.internalProp, Decl(component.d.ts, 1, 63))
>P : Symbol(P, Decl(component.d.ts, 1, 28))
}
export interface Prop {
>Prop : Symbol(Prop, Decl(component.d.ts, 3, 1))
a: number,
>a : Symbol(Prop.a, Decl(component.d.ts, 5, 23))
b: string
>b : Symbol(Prop.b, Decl(component.d.ts, 6, 14))
}
=== tests/cases/conformance/jsx/file.jsx ===
import { MyComp, Prop } from "./component";
>MyComp : Symbol(MyComp, Decl(file.jsx, 0, 8))
>Prop : Symbol(Prop, Decl(file.jsx, 0, 16))
import * as React from "react";
>React : Symbol(React, Decl(file.jsx, 1, 6))
let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
>x : Symbol(x, Decl(file.jsx, 3, 3))
>MyComp : Symbol(MyComp, Decl(file.jsx, 0, 8))
>Prop : Symbol(Prop, Decl(file.jsx, 0, 16))
>a : Symbol(a, Decl(file.jsx, 3, 21))
>b : Symbol(b, Decl(file.jsx, 3, 28))

View File

@@ -0,0 +1,44 @@
=== tests/cases/conformance/jsx/component.d.ts ===
import * as React from "react";
>React : typeof React
export declare class MyComp<P> extends React.Component<P, {}> {
>MyComp : MyComp<P>
>P : P
>React.Component : React.Component<P, {}>
>React : typeof React
>Component : typeof React.Component
>P : P
internalProp: P;
>internalProp : P
>P : P
}
export interface Prop {
>Prop : Prop
a: number,
>a : number
b: string
>b : string
}
=== tests/cases/conformance/jsx/file.jsx ===
import { MyComp, Prop } from "./component";
>MyComp : typeof MyComp
>Prop : any
import * as React from "react";
>React : typeof React
let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js
>x : JSX.Element
><MyComp<Prop> a={10} b="hi" /> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>a : number
>10 : 10
>b : string

View File

@@ -0,0 +1,145 @@
tests/cases/conformance/jsx/file.tsx(16,19): error TS2322: Type '{ a: number; b: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
Type '{ a: number; b: number; }' is not assignable to type 'Prop'.
Types of property 'b' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(18,19): error TS2322: Type '{ a: number; b: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
Type '{ a: number; b: number; }' is not assignable to type 'Prop'.
Types of property 'b' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(20,13): error TS2558: Expected 1 type arguments, but got 2.
tests/cases/conformance/jsx/file.tsx(22,13): error TS2558: Expected 1 type arguments, but got 2.
tests/cases/conformance/jsx/file.tsx(24,12): error TS1099: Type argument list cannot be empty.
tests/cases/conformance/jsx/file.tsx(26,12): error TS1099: Type argument list cannot be empty.
tests/cases/conformance/jsx/file.tsx(39,14): error TS2344: Type 'Prop' does not satisfy the constraint '{ a: string; }'.
Types of property 'a' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(39,20): error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
Type '{ a: number; b: string; }' is not assignable to type '{ a: string; }'.
Types of property 'a' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(41,14): error TS2344: Type 'Prop' does not satisfy the constraint '{ a: string; }'.
tests/cases/conformance/jsx/file.tsx(41,20): error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
Type '{ a: number; b: string; }' is not assignable to type '{ a: string; }'.
Types of property 'a' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(47,14): error TS2558: Expected 1-2 type arguments, but got 3.
tests/cases/conformance/jsx/file.tsx(47,53): error TS2339: Property 'b' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
tests/cases/conformance/jsx/file.tsx(49,14): error TS2558: Expected 1-2 type arguments, but got 3.
tests/cases/conformance/jsx/file.tsx(49,53): error TS2339: Property 'b' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
tests/cases/conformance/jsx/file.tsx(51,40): error TS2322: Type '{ a: string; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, { b: number; }>> & { a: string; } & { b: number; } & { children?: ReactNode; }'.
Type '{ a: string; b: string; }' is not assignable to type '{ b: number; }'.
Types of property 'b' are incompatible.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/jsx/file.tsx(53,40): error TS2322: Type '{ a: string; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, { b: number; }>> & { a: string; } & { b: number; } & { children?: ReactNode; }'.
Type '{ a: string; b: string; }' is not assignable to type '{ b: number; }'.
Types of property 'b' are incompatible.
Type 'string' is not assignable to type 'number'.
==== tests/cases/conformance/jsx/file.tsx (16 errors) ====
import React = require('react');
interface Prop {
a: number,
b: string
}
declare class MyComp<P> extends React.Component<P, {}> {
internalProp: P;
}
let x = <MyComp<Prop> a={10} b="hi" />; // OK
x = <MyComp<Prop> a={10} b="hi"></MyComp>; // OK
x = <MyComp<Prop> a={10} b={20} />; // error
~~~~~~~~~~~~~
!!! error TS2322: Type '{ a: number; b: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
!!! error TS2322: Type '{ a: number; b: number; }' is not assignable to type 'Prop'.
!!! error TS2322: Types of property 'b' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
x = <MyComp<Prop> a={10} b={20}></MyComp>; // error
~~~~~~~~~~~~~
!!! error TS2322: Type '{ a: number; b: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp<Prop>> & Prop & { children?: ReactNode; }'.
!!! error TS2322: Type '{ a: number; b: number; }' is not assignable to type 'Prop'.
!!! error TS2322: Types of property 'b' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
x = <MyComp<Prop, Prop> a={10} b="hi" />; // error
~~~~~~~~~~
!!! error TS2558: Expected 1 type arguments, but got 2.
x = <MyComp<Prop, Prop> a={10} b="hi"></MyComp>; // error
~~~~~~~~~~
!!! error TS2558: Expected 1 type arguments, but got 2.
x = <MyComp<> a={10} b="hi" />; // error
~~
!!! error TS1099: Type argument list cannot be empty.
x = <MyComp<> a={10} b="hi"></MyComp>; // error
~~
!!! error TS1099: Type argument list cannot be empty.
x= <MyComp<{}> /> // OK
x= <MyComp<{}>></MyComp> // OK
declare class MyComp2<P extends { a: string }, P2 = {}> extends React.Component<P & P2, {}> {
internalProp: [P, P2];
}
x = <MyComp2<{a: string, b: string}> a="a" b="b" />; // OK
x = <MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2>; // OK
x = <MyComp2<Prop> a={10} b="hi" />; // error
~~~~
!!! error TS2344: Type 'Prop' does not satisfy the constraint '{ a: string; }'.
!!! error TS2344: Types of property 'a' are incompatible.
!!! error TS2344: Type 'number' is not assignable to type 'string'.
~~~~~~~~~~~~~
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type '{ a: string; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
x = <MyComp2<Prop> a={10} b="hi"></MyComp2>; // error
~~~~
!!! error TS2344: Type 'Prop' does not satisfy the constraint '{ a: string; }'.
~~~~~~~~~~~~~
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
!!! error TS2322: Type '{ a: number; b: string; }' is not assignable to type '{ a: string; }'.
!!! error TS2322: Types of property 'a' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi" />; // OK
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2>; // OK
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" />; // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 1-2 type arguments, but got 3.
~~~~~~
!!! error TS2339: Property 'b' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2>; // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2558: Expected 1-2 type arguments, but got 3.
~~~~~~
!!! error TS2339: Property 'b' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, {}>> & { a: string; } & { children?: ReactNode; }'.
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi" />; // error
~~~~~~~~~~~~~
!!! error TS2322: Type '{ a: string; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, { b: number; }>> & { a: string; } & { b: number; } & { children?: ReactNode; }'.
!!! error TS2322: Type '{ a: string; b: string; }' is not assignable to type '{ b: number; }'.
!!! error TS2322: Types of property 'b' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2>; // error
~~~~~~~~~~~~~
!!! error TS2322: Type '{ a: string; b: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<MyComp2<{ a: string; }, { b: number; }>> & { a: string; } & { b: number; } & { children?: ReactNode; }'.
!!! error TS2322: Type '{ a: string; b: string; }' is not assignable to type '{ b: number; }'.
!!! error TS2322: Types of property 'b' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'number'.

View File

@@ -0,0 +1,80 @@
//// [file.tsx]
import React = require('react');
interface Prop {
a: number,
b: string
}
declare class MyComp<P> extends React.Component<P, {}> {
internalProp: P;
}
let x = <MyComp<Prop> a={10} b="hi" />; // OK
x = <MyComp<Prop> a={10} b="hi"></MyComp>; // OK
x = <MyComp<Prop> a={10} b={20} />; // error
x = <MyComp<Prop> a={10} b={20}></MyComp>; // error
x = <MyComp<Prop, Prop> a={10} b="hi" />; // error
x = <MyComp<Prop, Prop> a={10} b="hi"></MyComp>; // error
x = <MyComp<> a={10} b="hi" />; // error
x = <MyComp<> a={10} b="hi"></MyComp>; // error
x= <MyComp<{}> /> // OK
x= <MyComp<{}>></MyComp> // OK
declare class MyComp2<P extends { a: string }, P2 = {}> extends React.Component<P & P2, {}> {
internalProp: [P, P2];
}
x = <MyComp2<{a: string, b: string}> a="a" b="b" />; // OK
x = <MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2>; // OK
x = <MyComp2<Prop> a={10} b="hi" />; // error
x = <MyComp2<Prop> a={10} b="hi"></MyComp2>; // error
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi" />; // OK
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2>; // OK
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" />; // error
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2>; // error
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi" />; // error
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2>; // error
//// [file.jsx]
"use strict";
exports.__esModule = true;
var React = require("react");
var x = <MyComp a={10} b="hi"/>; // OK
x = <MyComp a={10} b="hi"></MyComp>; // OK
x = <MyComp a={10} b={20}/>; // error
x = <MyComp a={10} b={20}></MyComp>; // error
x = <MyComp a={10} b="hi"/>; // error
x = <MyComp a={10} b="hi"></MyComp>; // error
x = <MyComp a={10} b="hi"/>; // error
x = <MyComp a={10} b="hi"></MyComp>; // error
x = <MyComp />; // OK
x = <MyComp></MyComp>; // OK
x = <MyComp2 a="a" b="b"/>; // OK
x = <MyComp2 a="a" b="b"></MyComp2>; // OK
x = <MyComp2 a={10} b="hi"/>; // error
x = <MyComp2 a={10} b="hi"></MyComp2>; // error
x = <MyComp2 a="hi" b="hi"/>; // OK
x = <MyComp2 a="hi" b="hi"></MyComp2>; // OK
x = <MyComp2 a="hi" b="hi"/>; // error
x = <MyComp2 a="hi" b="hi"></MyComp2>; // error
x = <MyComp2 a="hi" b="hi"/>; // error
x = <MyComp2 a="hi" b="hi"></MyComp2>; // error

View File

@@ -0,0 +1,197 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : Symbol(React, Decl(file.tsx, 0, 0))
interface Prop {
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
a: number,
>a : Symbol(Prop.a, Decl(file.tsx, 2, 16))
b: string
>b : Symbol(Prop.b, Decl(file.tsx, 3, 14))
}
declare class MyComp<P> extends React.Component<P, {}> {
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>P : Symbol(P, Decl(file.tsx, 7, 21))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>React : Symbol(React, Decl(file.tsx, 0, 0))
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>P : Symbol(P, Decl(file.tsx, 7, 21))
internalProp: P;
>internalProp : Symbol(MyComp.internalProp, Decl(file.tsx, 7, 56))
>P : Symbol(P, Decl(file.tsx, 7, 21))
}
let x = <MyComp<Prop> a={10} b="hi" />; // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 11, 21))
>b : Symbol(b, Decl(file.tsx, 11, 28))
x = <MyComp<Prop> a={10} b="hi"></MyComp>; // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 13, 17))
>b : Symbol(b, Decl(file.tsx, 13, 24))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
x = <MyComp<Prop> a={10} b={20} />; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 15, 17))
>b : Symbol(b, Decl(file.tsx, 15, 24))
x = <MyComp<Prop> a={10} b={20}></MyComp>; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 17, 17))
>b : Symbol(b, Decl(file.tsx, 17, 24))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
x = <MyComp<Prop, Prop> a={10} b="hi" />; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 19, 23))
>b : Symbol(b, Decl(file.tsx, 19, 30))
x = <MyComp<Prop, Prop> a={10} b="hi"></MyComp>; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 21, 23))
>b : Symbol(b, Decl(file.tsx, 21, 30))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
x = <MyComp<> a={10} b="hi" />; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>a : Symbol(a, Decl(file.tsx, 23, 13))
>b : Symbol(b, Decl(file.tsx, 23, 20))
x = <MyComp<> a={10} b="hi"></MyComp>; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>a : Symbol(a, Decl(file.tsx, 25, 13))
>b : Symbol(b, Decl(file.tsx, 25, 20))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
x= <MyComp<{}> /> // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
x= <MyComp<{}>></MyComp> // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
>MyComp : Symbol(MyComp, Decl(file.tsx, 5, 1))
declare class MyComp2<P extends { a: string }, P2 = {}> extends React.Component<P & P2, {}> {
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>P : Symbol(P, Decl(file.tsx, 31, 22))
>a : Symbol(a, Decl(file.tsx, 31, 33))
>P2 : Symbol(P2, Decl(file.tsx, 31, 46))
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>React : Symbol(React, Decl(file.tsx, 0, 0))
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55), Decl(react.d.ts, 161, 66))
>P : Symbol(P, Decl(file.tsx, 31, 22))
>P2 : Symbol(P2, Decl(file.tsx, 31, 46))
internalProp: [P, P2];
>internalProp : Symbol(MyComp2.internalProp, Decl(file.tsx, 31, 93))
>P : Symbol(P, Decl(file.tsx, 31, 22))
>P2 : Symbol(P2, Decl(file.tsx, 31, 46))
}
x = <MyComp2<{a: string, b: string}> a="a" b="b" />; // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 34, 14))
>b : Symbol(b, Decl(file.tsx, 34, 24))
>a : Symbol(a, Decl(file.tsx, 34, 36))
>b : Symbol(b, Decl(file.tsx, 34, 42))
x = <MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2>; // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 36, 14))
>b : Symbol(b, Decl(file.tsx, 36, 24))
>a : Symbol(a, Decl(file.tsx, 36, 36))
>b : Symbol(b, Decl(file.tsx, 36, 42))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
x = <MyComp2<Prop> a={10} b="hi" />; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 38, 18))
>b : Symbol(b, Decl(file.tsx, 38, 25))
x = <MyComp2<Prop> a={10} b="hi"></MyComp2>; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 40, 18))
>b : Symbol(b, Decl(file.tsx, 40, 25))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi" />; // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 42, 14))
>b : Symbol(b, Decl(file.tsx, 42, 27))
>a : Symbol(a, Decl(file.tsx, 42, 38))
>b : Symbol(b, Decl(file.tsx, 42, 45))
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2>; // OK
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 44, 14))
>b : Symbol(b, Decl(file.tsx, 44, 27))
>a : Symbol(a, Decl(file.tsx, 44, 38))
>b : Symbol(b, Decl(file.tsx, 44, 45))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" />; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 46, 14))
>b : Symbol(b, Decl(file.tsx, 46, 27))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 46, 44))
>b : Symbol(b, Decl(file.tsx, 46, 51))
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2>; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 48, 14))
>b : Symbol(b, Decl(file.tsx, 48, 27))
>Prop : Symbol(Prop, Decl(file.tsx, 0, 32))
>a : Symbol(a, Decl(file.tsx, 48, 44))
>b : Symbol(b, Decl(file.tsx, 48, 51))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi" />; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 50, 14))
>b : Symbol(b, Decl(file.tsx, 50, 27))
>a : Symbol(a, Decl(file.tsx, 50, 38))
>b : Symbol(b, Decl(file.tsx, 50, 45))
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2>; // error
>x : Symbol(x, Decl(file.tsx, 11, 3))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))
>a : Symbol(a, Decl(file.tsx, 52, 14))
>b : Symbol(b, Decl(file.tsx, 52, 27))
>a : Symbol(a, Decl(file.tsx, 52, 38))
>b : Symbol(b, Decl(file.tsx, 52, 45))
>MyComp2 : Symbol(MyComp2, Decl(file.tsx, 29, 24))

View File

@@ -0,0 +1,248 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : typeof React
interface Prop {
>Prop : Prop
a: number,
>a : number
b: string
>b : string
}
declare class MyComp<P> extends React.Component<P, {}> {
>MyComp : MyComp<P>
>P : P
>React.Component : React.Component<P, {}>
>React : typeof React
>Component : typeof React.Component
>P : P
internalProp: P;
>internalProp : P
>P : P
}
let x = <MyComp<Prop> a={10} b="hi" />; // OK
>x : JSX.Element
><MyComp<Prop> a={10} b="hi" /> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>a : number
>10 : 10
>b : string
x = <MyComp<Prop> a={10} b="hi"></MyComp>; // OK
>x = <MyComp<Prop> a={10} b="hi"></MyComp> : JSX.Element
>x : JSX.Element
><MyComp<Prop> a={10} b="hi"></MyComp> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>a : number
>10 : 10
>b : string
>MyComp : typeof MyComp
x = <MyComp<Prop> a={10} b={20} />; // error
>x = <MyComp<Prop> a={10} b={20} /> : JSX.Element
>x : JSX.Element
><MyComp<Prop> a={10} b={20} /> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>a : number
>10 : 10
>b : number
>20 : 20
x = <MyComp<Prop> a={10} b={20}></MyComp>; // error
>x = <MyComp<Prop> a={10} b={20}></MyComp> : JSX.Element
>x : JSX.Element
><MyComp<Prop> a={10} b={20}></MyComp> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>a : number
>10 : 10
>b : number
>20 : 20
>MyComp : typeof MyComp
x = <MyComp<Prop, Prop> a={10} b="hi" />; // error
>x = <MyComp<Prop, Prop> a={10} b="hi" /> : JSX.Element
>x : JSX.Element
><MyComp<Prop, Prop> a={10} b="hi" /> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>Prop : Prop
>a : number
>10 : 10
>b : string
x = <MyComp<Prop, Prop> a={10} b="hi"></MyComp>; // error
>x = <MyComp<Prop, Prop> a={10} b="hi"></MyComp> : JSX.Element
>x : JSX.Element
><MyComp<Prop, Prop> a={10} b="hi"></MyComp> : JSX.Element
>MyComp : typeof MyComp
>Prop : Prop
>Prop : Prop
>a : number
>10 : 10
>b : string
>MyComp : typeof MyComp
x = <MyComp<> a={10} b="hi" />; // error
>x = <MyComp<> a={10} b="hi" /> : JSX.Element
>x : JSX.Element
><MyComp<> a={10} b="hi" /> : JSX.Element
>MyComp : typeof MyComp
>a : number
>10 : 10
>b : string
x = <MyComp<> a={10} b="hi"></MyComp>; // error
>x = <MyComp<> a={10} b="hi"></MyComp> : JSX.Element
>x : JSX.Element
><MyComp<> a={10} b="hi"></MyComp> : JSX.Element
>MyComp : typeof MyComp
>a : number
>10 : 10
>b : string
>MyComp : typeof MyComp
x= <MyComp<{}> /> // OK
>x= <MyComp<{}> /> : JSX.Element
>x : JSX.Element
><MyComp<{}> /> : JSX.Element
>MyComp : typeof MyComp
x= <MyComp<{}>></MyComp> // OK
>x= <MyComp<{}>></MyComp> : JSX.Element
>x : JSX.Element
><MyComp<{}>></MyComp> : JSX.Element
>MyComp : typeof MyComp
>MyComp : typeof MyComp
declare class MyComp2<P extends { a: string }, P2 = {}> extends React.Component<P & P2, {}> {
>MyComp2 : MyComp2<P, P2>
>P : P
>a : string
>P2 : P2
>React.Component : React.Component<P & P2, {}>
>React : typeof React
>Component : typeof React.Component
>P : P
>P2 : P2
internalProp: [P, P2];
>internalProp : [P, P2]
>P : P
>P2 : P2
}
x = <MyComp2<{a: string, b: string}> a="a" b="b" />; // OK
>x = <MyComp2<{a: string, b: string}> a="a" b="b" /> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string, b: string}> a="a" b="b" /> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : string
>a : string
>b : string
x = <MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2>; // OK
>x = <MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : string
>a : string
>b : string
>MyComp2 : typeof MyComp2
x = <MyComp2<Prop> a={10} b="hi" />; // error
>x = <MyComp2<Prop> a={10} b="hi" /> : JSX.Element
>x : JSX.Element
><MyComp2<Prop> a={10} b="hi" /> : JSX.Element
>MyComp2 : typeof MyComp2
>Prop : Prop
>a : number
>10 : 10
>b : string
x = <MyComp2<Prop> a={10} b="hi"></MyComp2>; // error
>x = <MyComp2<Prop> a={10} b="hi"></MyComp2> : JSX.Element
>x : JSX.Element
><MyComp2<Prop> a={10} b="hi"></MyComp2> : JSX.Element
>MyComp2 : typeof MyComp2
>Prop : Prop
>a : number
>10 : 10
>b : string
>MyComp2 : typeof MyComp2
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi" />; // OK
>x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi" /> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string}, {b: string}> a="hi" b="hi" /> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : string
>a : string
>b : string
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2>; // OK
>x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : string
>a : string
>b : string
>MyComp2 : typeof MyComp2
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" />; // error
>x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" /> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" /> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : string
>Prop : Prop
>a : string
>b : string
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2>; // error
>x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : string
>Prop : Prop
>a : string
>b : string
>MyComp2 : typeof MyComp2
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi" />; // error
>x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi" /> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string}, {b: number}> a="hi" b="hi" /> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : number
>a : string
>b : string
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2>; // error
>x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2> : JSX.Element
>x : JSX.Element
><MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2> : JSX.Element
>MyComp2 : typeof MyComp2
>a : string
>b : number
>a : string
>b : string
>MyComp2 : typeof MyComp2

View File

@@ -0,0 +1,23 @@
// @jsx: preserve
// @noLib: true
// @skipLibCheck: true
// @libFiles: react.d.ts,lib.d.ts
// @allowJs: true
// @outDir: ./out
// @checkJs: true
// @filename: component.d.ts
import * as React from "react";
export declare class MyComp<P> extends React.Component<P, {}> {
internalProp: P;
}
export interface Prop {
a: number,
b: string
}
// @filename: file.jsx
import { MyComp, Prop } from "./component";
import * as React from "react";
let x = <MyComp<Prop> a={10} b="hi" />; // error, no type arguments in js

View File

@@ -0,0 +1,59 @@
// @filename: file.tsx
// @jsx: preserve
// @noLib: true
// @skipLibCheck: true
// @libFiles: react.d.ts,lib.d.ts
import React = require('react');
interface Prop {
a: number,
b: string
}
declare class MyComp<P> extends React.Component<P, {}> {
internalProp: P;
}
let x = <MyComp<Prop> a={10} b="hi" />; // OK
x = <MyComp<Prop> a={10} b="hi"></MyComp>; // OK
x = <MyComp<Prop> a={10} b={20} />; // error
x = <MyComp<Prop> a={10} b={20}></MyComp>; // error
x = <MyComp<Prop, Prop> a={10} b="hi" />; // error
x = <MyComp<Prop, Prop> a={10} b="hi"></MyComp>; // error
x = <MyComp<> a={10} b="hi" />; // error
x = <MyComp<> a={10} b="hi"></MyComp>; // error
x= <MyComp<{}> /> // OK
x= <MyComp<{}>></MyComp> // OK
declare class MyComp2<P extends { a: string }, P2 = {}> extends React.Component<P & P2, {}> {
internalProp: [P, P2];
}
x = <MyComp2<{a: string, b: string}> a="a" b="b" />; // OK
x = <MyComp2<{a: string, b: string}> a="a" b="b"></MyComp2>; // OK
x = <MyComp2<Prop> a={10} b="hi" />; // error
x = <MyComp2<Prop> a={10} b="hi"></MyComp2>; // error
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi" />; // OK
x = <MyComp2<{a: string}, {b: string}> a="hi" b="hi"></MyComp2>; // OK
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi" />; // error
x = <MyComp2<{a: string}, {b: string}, Prop> a="hi" b="hi"></MyComp2>; // error
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi" />; // error
x = <MyComp2<{a: string}, {b: number}> a="hi" b="hi"></MyComp2>; // error