Baseline arity checks for jsx sfc tags (#36643)
Finish comment PR feedback
This commit is contained in:
parent
e536c89872
commit
7d8dc730b7
|
@ -940,6 +940,7 @@ namespace ts {
|
|||
if (jsxPragma) {
|
||||
const chosenpragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma;
|
||||
file.localJsxFactory = parseIsolatedEntityName(chosenpragma.arguments.factory, languageVersion);
|
||||
visitNode(file.localJsxFactory, markAsSynthetic);
|
||||
if (file.localJsxFactory) {
|
||||
return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText;
|
||||
}
|
||||
|
@ -950,6 +951,7 @@ namespace ts {
|
|||
_jsxNamespace = "React" as __String;
|
||||
if (compilerOptions.jsxFactory) {
|
||||
_jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion);
|
||||
visitNode(_jsxFactoryEntity, markAsSynthetic);
|
||||
if (_jsxFactoryEntity) {
|
||||
_jsxNamespace = getFirstIdentifier(_jsxFactoryEntity).escapedText;
|
||||
}
|
||||
|
@ -958,7 +960,16 @@ namespace ts {
|
|||
_jsxNamespace = escapeLeadingUnderscores(compilerOptions.reactNamespace);
|
||||
}
|
||||
}
|
||||
if (!_jsxFactoryEntity) {
|
||||
_jsxFactoryEntity = createQualifiedName(createIdentifier(unescapeLeadingUnderscores(_jsxNamespace)), "createElement");
|
||||
}
|
||||
return _jsxNamespace;
|
||||
|
||||
function markAsSynthetic(node: Node): VisitResult<Node> {
|
||||
node.pos = -1;
|
||||
node.end = -1;
|
||||
return visitEachChild(node, markAsSynthetic, nullTransformationContext);
|
||||
}
|
||||
}
|
||||
|
||||
function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) {
|
||||
|
@ -2802,8 +2813,8 @@ namespace ts {
|
|||
const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(name) ? meaning & SymbolFlags.Value : 0);
|
||||
let symbol: Symbol | undefined;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
const message = meaning === namespaceMeaning ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name));
|
||||
const symbolFromJSPrototype = isInJSFile(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined;
|
||||
const message = meaning === namespaceMeaning || nodeIsSynthesized(name) ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name));
|
||||
const symbolFromJSPrototype = isInJSFile(name) && !nodeIsSynthesized(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined;
|
||||
symbol = resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true);
|
||||
if (!symbol) {
|
||||
return symbolFromJSPrototype;
|
||||
|
@ -2846,7 +2857,7 @@ namespace ts {
|
|||
throw Debug.assertNever(name, "Unknown entity name kind.");
|
||||
}
|
||||
Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
|
||||
if (isEntityName(name) && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment)) {
|
||||
if (!nodeIsSynthesized(name) && isEntityName(name) && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment)) {
|
||||
markSymbolOfAliasDeclarationIfTypeOnly(getAliasDeclarationFromName(name), symbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ true);
|
||||
}
|
||||
return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol);
|
||||
|
@ -24391,7 +24402,7 @@ namespace ts {
|
|||
// can be specified by users through attributes property.
|
||||
const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node);
|
||||
const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*inferenceContext*/ undefined, checkMode);
|
||||
return checkTypeRelatedToAndOptionallyElaborate(
|
||||
return checkTagNameDoesNotExpectTooManyArguments() && checkTypeRelatedToAndOptionallyElaborate(
|
||||
attributesType,
|
||||
paramType,
|
||||
relation,
|
||||
|
@ -24400,6 +24411,80 @@ namespace ts {
|
|||
/*headMessage*/ undefined,
|
||||
containingMessageChain,
|
||||
errorOutputContainer);
|
||||
|
||||
function checkTagNameDoesNotExpectTooManyArguments(): boolean {
|
||||
const tagType = isJsxOpeningElement(node) || isJsxSelfClosingElement(node) && !isJsxIntrinsicIdentifier(node.tagName) ? checkExpression(node.tagName) : undefined;
|
||||
if (!tagType) {
|
||||
return true;
|
||||
}
|
||||
const tagCallSignatures = getSignaturesOfType(tagType, SignatureKind.Call);
|
||||
if (!length(tagCallSignatures)) {
|
||||
return true;
|
||||
}
|
||||
const factory = getJsxFactoryEntity(node);
|
||||
if (!factory) {
|
||||
return true;
|
||||
}
|
||||
const factorySymbol = resolveEntityName(factory, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, node);
|
||||
if (!factorySymbol) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const factoryType = getTypeOfSymbol(factorySymbol);
|
||||
const callSignatures = getSignaturesOfType(factoryType, SignatureKind.Call);
|
||||
if (!length(callSignatures)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let hasFirstParamSignatures = false;
|
||||
let maxParamCount = 0;
|
||||
// Check that _some_ first parameter expects a FC-like thing, and that some overload of the SFC expects an acceptable number of arguments
|
||||
for (const sig of callSignatures) {
|
||||
const firstparam = getTypeAtPosition(sig, 0);
|
||||
const signaturesOfParam = getSignaturesOfType(firstparam, SignatureKind.Call);
|
||||
if (!length(signaturesOfParam)) continue;
|
||||
for (const paramSig of signaturesOfParam) {
|
||||
hasFirstParamSignatures = true;
|
||||
if (hasEffectiveRestParameter(paramSig)) {
|
||||
return true; // some signature has a rest param, so function components can have an arbitrary number of arguments
|
||||
}
|
||||
const paramCount = getParameterCount(paramSig);
|
||||
if (paramCount > maxParamCount) {
|
||||
maxParamCount = paramCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasFirstParamSignatures) {
|
||||
// Not a single signature had a first parameter which expected a signature - for back compat, and
|
||||
// to guard against generic factories which won't have signatures directly, do not error
|
||||
return true;
|
||||
}
|
||||
let absoluteMinArgCount = Infinity;
|
||||
for (const tagSig of tagCallSignatures) {
|
||||
const tagRequiredArgCount = getMinArgumentCount(tagSig);
|
||||
if (tagRequiredArgCount < absoluteMinArgCount) {
|
||||
absoluteMinArgCount = tagRequiredArgCount;
|
||||
}
|
||||
}
|
||||
if (absoluteMinArgCount <= maxParamCount) {
|
||||
return true; // some signature accepts the number of arguments the function component provides
|
||||
}
|
||||
|
||||
if (reportErrors) {
|
||||
const diag = createDiagnosticForNode(node.tagName, Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, entityNameToString(node.tagName), absoluteMinArgCount, entityNameToString(factory), maxParamCount);
|
||||
const tagNameDeclaration = getSymbolAtLocation(node.tagName)?.valueDeclaration;
|
||||
if (tagNameDeclaration) {
|
||||
addRelatedInfo(diag, createDiagnosticForNode(tagNameDeclaration, Diagnostics._0_is_declared_here, entityNameToString(node.tagName)));
|
||||
}
|
||||
if (errorOutputContainer && errorOutputContainer.skipLogging) {
|
||||
(errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag);
|
||||
}
|
||||
if (!errorOutputContainer.skipLogging) {
|
||||
diagnostics.add(diag);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getSignatureApplicabilityError(
|
||||
|
@ -35282,6 +35367,10 @@ namespace ts {
|
|||
return literalTypeToNode(<FreshableType>type, node, tracker);
|
||||
}
|
||||
|
||||
function getJsxFactoryEntity(location: Node) {
|
||||
return location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity;
|
||||
}
|
||||
|
||||
function createResolver(): EmitResolver {
|
||||
// this variable and functions that use it are deliberately moved here from the outer scope
|
||||
// to avoid scope pollution
|
||||
|
@ -35353,7 +35442,7 @@ namespace ts {
|
|||
const symbol = node && getSymbolOfNode(node);
|
||||
return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late);
|
||||
},
|
||||
getJsxFactoryEntity: location => location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity,
|
||||
getJsxFactoryEntity,
|
||||
getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations {
|
||||
accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217
|
||||
const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor;
|
||||
|
|
|
@ -4292,6 +4292,10 @@
|
|||
"category": "Message",
|
||||
"code": 6228
|
||||
},
|
||||
"Tag '{0}' expects at least '{1}' arguments, but the JSX factory '{2}' provides at most '{3}'.": {
|
||||
"category": "Error",
|
||||
"code": 6229
|
||||
},
|
||||
|
||||
"Projects to reference": {
|
||||
"category": "Message",
|
||||
|
|
|
@ -864,14 +864,17 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
export function entityNameToString(name: EntityNameOrEntityNameExpression): string {
|
||||
export function entityNameToString(name: EntityNameOrEntityNameExpression | JsxTagNameExpression | PrivateIdentifier): string {
|
||||
switch (name.kind) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return "this";
|
||||
case SyntaxKind.PrivateIdentifier:
|
||||
case SyntaxKind.Identifier:
|
||||
return getFullWidth(name) === 0 ? idText(name) : getTextOfNode(name);
|
||||
case SyntaxKind.QualifiedName:
|
||||
return entityNameToString(name.left) + "." + entityNameToString(name.right);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
if (isIdentifier(name.name)) {
|
||||
if (isIdentifier(name.name) || isPrivateIdentifier(name.name)) {
|
||||
return entityNameToString(name.expression) + "." + entityNameToString(name.name);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx(19,12): error TS6229: Tag 'MyComp4' expects at least '4' arguments, but the JSX factory 'React.createElement' provides at most '2'.
|
||||
tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx(20,12): error TS6229: Tag 'MyComp3' expects at least '3' arguments, but the JSX factory 'React.createElement' provides at most '2'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx (2 errors) ====
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
interface MyProps {
|
||||
x: number;
|
||||
}
|
||||
|
||||
function MyComp4(props: MyProps, context: any, bad: any, verybad: any) {
|
||||
return <div></div>;
|
||||
}
|
||||
function MyComp3(props: MyProps, context: any, bad: any) {
|
||||
return <div></div>;
|
||||
}
|
||||
function MyComp2(props: MyProps, context: any) {
|
||||
return <div></div>
|
||||
}
|
||||
|
||||
const a = <MyComp4 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
~~~~~~~
|
||||
!!! error TS6229: Tag 'MyComp4' expects at least '4' arguments, but the JSX factory 'React.createElement' provides at most '2'.
|
||||
!!! related TS2728 tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx:9:10: 'MyComp4' is declared here.
|
||||
const b = <MyComp3 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
~~~~~~~
|
||||
!!! error TS6229: Tag 'MyComp3' expects at least '3' arguments, but the JSX factory 'React.createElement' provides at most '2'.
|
||||
!!! related TS2728 tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx:12:10: 'MyComp3' is declared here.
|
||||
const c = <MyComp2 x={2}/>; // Should be OK, `context` is allowed, per react rules
|
||||
|
||||
declare function MyTagWithOptionalNonJSXBits(props: MyProps, context: any, nonReactArg?: string): JSX.Element;
|
||||
const d = <MyTagWithOptionalNonJSXBits x={2} />; // Technically OK, but probably questionable
|
|
@ -0,0 +1,44 @@
|
|||
//// [jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx]
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
interface MyProps {
|
||||
x: number;
|
||||
}
|
||||
|
||||
function MyComp4(props: MyProps, context: any, bad: any, verybad: any) {
|
||||
return <div></div>;
|
||||
}
|
||||
function MyComp3(props: MyProps, context: any, bad: any) {
|
||||
return <div></div>;
|
||||
}
|
||||
function MyComp2(props: MyProps, context: any) {
|
||||
return <div></div>
|
||||
}
|
||||
|
||||
const a = <MyComp4 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
const b = <MyComp3 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
const c = <MyComp2 x={2}/>; // Should be OK, `context` is allowed, per react rules
|
||||
|
||||
declare function MyTagWithOptionalNonJSXBits(props: MyProps, context: any, nonReactArg?: string): JSX.Element;
|
||||
const d = <MyTagWithOptionalNonJSXBits x={2} />; // Technically OK, but probably questionable
|
||||
|
||||
//// [jsxIssuesErrorWhenTagExpectsTooManyArguments.js]
|
||||
"use strict";
|
||||
/// <reference path="react16.d.ts" />
|
||||
exports.__esModule = true;
|
||||
var React = require("react");
|
||||
function MyComp4(props, context, bad, verybad) {
|
||||
return React.createElement("div", null);
|
||||
}
|
||||
function MyComp3(props, context, bad) {
|
||||
return React.createElement("div", null);
|
||||
}
|
||||
function MyComp2(props, context) {
|
||||
return React.createElement("div", null);
|
||||
}
|
||||
var a = React.createElement(MyComp4, { x: 2 }); // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
var b = React.createElement(MyComp3, { x: 2 }); // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
var c = React.createElement(MyComp2, { x: 2 }); // Should be OK, `context` is allowed, per react rules
|
||||
var d = React.createElement(MyTagWithOptionalNonJSXBits, { x: 2 }); // Technically OK, but probably questionable
|
|
@ -0,0 +1,76 @@
|
|||
=== tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
|
||||
import * as React from "react";
|
||||
>React : Symbol(React, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 2, 6))
|
||||
|
||||
interface MyProps {
|
||||
>MyProps : Symbol(MyProps, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 2, 31))
|
||||
|
||||
x: number;
|
||||
>x : Symbol(MyProps.x, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 4, 19))
|
||||
}
|
||||
|
||||
function MyComp4(props: MyProps, context: any, bad: any, verybad: any) {
|
||||
>MyComp4 : Symbol(MyComp4, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 6, 1))
|
||||
>props : Symbol(props, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 8, 17))
|
||||
>MyProps : Symbol(MyProps, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 2, 31))
|
||||
>context : Symbol(context, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 8, 32))
|
||||
>bad : Symbol(bad, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 8, 46))
|
||||
>verybad : Symbol(verybad, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 8, 56))
|
||||
|
||||
return <div></div>;
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
|
||||
}
|
||||
function MyComp3(props: MyProps, context: any, bad: any) {
|
||||
>MyComp3 : Symbol(MyComp3, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 10, 1))
|
||||
>props : Symbol(props, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 11, 17))
|
||||
>MyProps : Symbol(MyProps, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 2, 31))
|
||||
>context : Symbol(context, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 11, 32))
|
||||
>bad : Symbol(bad, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 11, 46))
|
||||
|
||||
return <div></div>;
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
|
||||
}
|
||||
function MyComp2(props: MyProps, context: any) {
|
||||
>MyComp2 : Symbol(MyComp2, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 13, 1))
|
||||
>props : Symbol(props, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 14, 17))
|
||||
>MyProps : Symbol(MyProps, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 2, 31))
|
||||
>context : Symbol(context, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 14, 32))
|
||||
|
||||
return <div></div>
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2420, 114))
|
||||
}
|
||||
|
||||
const a = <MyComp4 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
>a : Symbol(a, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 18, 5))
|
||||
>MyComp4 : Symbol(MyComp4, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 6, 1))
|
||||
>x : Symbol(x, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 18, 18))
|
||||
|
||||
const b = <MyComp3 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
>b : Symbol(b, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 19, 5))
|
||||
>MyComp3 : Symbol(MyComp3, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 10, 1))
|
||||
>x : Symbol(x, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 19, 18))
|
||||
|
||||
const c = <MyComp2 x={2}/>; // Should be OK, `context` is allowed, per react rules
|
||||
>c : Symbol(c, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 20, 5))
|
||||
>MyComp2 : Symbol(MyComp2, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 13, 1))
|
||||
>x : Symbol(x, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 20, 19))
|
||||
|
||||
declare function MyTagWithOptionalNonJSXBits(props: MyProps, context: any, nonReactArg?: string): JSX.Element;
|
||||
>MyTagWithOptionalNonJSXBits : Symbol(MyTagWithOptionalNonJSXBits, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 20, 28))
|
||||
>props : Symbol(props, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 22, 45))
|
||||
>MyProps : Symbol(MyProps, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 2, 31))
|
||||
>context : Symbol(context, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 22, 60))
|
||||
>nonReactArg : Symbol(nonReactArg, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 22, 74))
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2367, 12))
|
||||
>Element : Symbol(JSX.Element, Decl(react16.d.ts, 2368, 23))
|
||||
|
||||
const d = <MyTagWithOptionalNonJSXBits x={2} />; // Technically OK, but probably questionable
|
||||
>d : Symbol(d, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 23, 5))
|
||||
>MyTagWithOptionalNonJSXBits : Symbol(MyTagWithOptionalNonJSXBits, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 20, 28))
|
||||
>x : Symbol(x, Decl(jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx, 23, 38))
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
=== tests/cases/compiler/jsxIssuesErrorWhenTagExpectsTooManyArguments.tsx ===
|
||||
/// <reference path="react16.d.ts" />
|
||||
|
||||
import * as React from "react";
|
||||
>React : typeof React
|
||||
|
||||
interface MyProps {
|
||||
x: number;
|
||||
>x : number
|
||||
}
|
||||
|
||||
function MyComp4(props: MyProps, context: any, bad: any, verybad: any) {
|
||||
>MyComp4 : (props: MyProps, context: any, bad: any, verybad: any) => JSX.Element
|
||||
>props : MyProps
|
||||
>context : any
|
||||
>bad : any
|
||||
>verybad : any
|
||||
|
||||
return <div></div>;
|
||||
><div></div> : JSX.Element
|
||||
>div : any
|
||||
>div : any
|
||||
}
|
||||
function MyComp3(props: MyProps, context: any, bad: any) {
|
||||
>MyComp3 : (props: MyProps, context: any, bad: any) => JSX.Element
|
||||
>props : MyProps
|
||||
>context : any
|
||||
>bad : any
|
||||
|
||||
return <div></div>;
|
||||
><div></div> : JSX.Element
|
||||
>div : any
|
||||
>div : any
|
||||
}
|
||||
function MyComp2(props: MyProps, context: any) {
|
||||
>MyComp2 : (props: MyProps, context: any) => JSX.Element
|
||||
>props : MyProps
|
||||
>context : any
|
||||
|
||||
return <div></div>
|
||||
><div></div> : JSX.Element
|
||||
>div : any
|
||||
>div : any
|
||||
}
|
||||
|
||||
const a = <MyComp4 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
>a : JSX.Element
|
||||
><MyComp4 x={2}/> : JSX.Element
|
||||
>MyComp4 : (props: MyProps, context: any, bad: any, verybad: any) => JSX.Element
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
const b = <MyComp3 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
>b : JSX.Element
|
||||
><MyComp3 x={2}/> : JSX.Element
|
||||
>MyComp3 : (props: MyProps, context: any, bad: any) => JSX.Element
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
const c = <MyComp2 x={2}/>; // Should be OK, `context` is allowed, per react rules
|
||||
>c : JSX.Element
|
||||
><MyComp2 x={2}/> : JSX.Element
|
||||
>MyComp2 : (props: MyProps, context: any) => JSX.Element
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
declare function MyTagWithOptionalNonJSXBits(props: MyProps, context: any, nonReactArg?: string): JSX.Element;
|
||||
>MyTagWithOptionalNonJSXBits : (props: MyProps, context: any, nonReactArg?: string) => JSX.Element
|
||||
>props : MyProps
|
||||
>context : any
|
||||
>nonReactArg : string
|
||||
>JSX : any
|
||||
|
||||
const d = <MyTagWithOptionalNonJSXBits x={2} />; // Technically OK, but probably questionable
|
||||
>d : JSX.Element
|
||||
><MyTagWithOptionalNonJSXBits x={2} /> : JSX.Element
|
||||
>MyTagWithOptionalNonJSXBits : (props: MyProps, context: any, nonReactArg?: string) => JSX.Element
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// @jsx: react
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
interface MyProps {
|
||||
x: number;
|
||||
}
|
||||
|
||||
function MyComp4(props: MyProps, context: any, bad: any, verybad: any) {
|
||||
return <div></div>;
|
||||
}
|
||||
function MyComp3(props: MyProps, context: any, bad: any) {
|
||||
return <div></div>;
|
||||
}
|
||||
function MyComp2(props: MyProps, context: any) {
|
||||
return <div></div>
|
||||
}
|
||||
|
||||
const a = <MyComp4 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
const b = <MyComp3 x={2}/>; // using `MyComp` as a component should error - it expects more arguments than react provides
|
||||
const c = <MyComp2 x={2}/>; // Should be OK, `context` is allowed, per react rules
|
||||
|
||||
declare function MyTagWithOptionalNonJSXBits(props: MyProps, context: any, nonReactArg?: string): JSX.Element;
|
||||
const d = <MyTagWithOptionalNonJSXBits x={2} />; // Technically OK, but probably questionable
|
Loading…
Reference in a new issue