JSX namespace names should not be considered expressions (#54104)

This commit is contained in:
Wesley Wigham 2023-05-09 10:45:58 -07:00 committed by GitHub
parent 59d3a38180
commit 02bb3108ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 187 additions and 59 deletions

View File

@ -776,6 +776,7 @@ import {
JSDocVariadicType,
JsxAttribute,
JsxAttributeLike,
JsxAttributeName,
JsxAttributes,
JsxChild,
JsxClosingElement,
@ -17026,19 +17027,31 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function getLiteralTypeFromPropertyName(name: PropertyName) {
function getLiteralTypeFromPropertyName(name: PropertyName | JsxAttributeName) {
if (isPrivateIdentifier(name)) {
return neverType;
}
return isIdentifier(name) ? getStringLiteralType(unescapeLeadingUnderscores(name.escapedText)) :
getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name));
if (isNumericLiteral(name)) {
return getRegularTypeOfLiteralType(checkExpression(name));
}
if (isComputedPropertyName(name)) {
return getRegularTypeOfLiteralType(checkComputedPropertyName(name));
}
const propertyName = getPropertyNameForPropertyNameNode(name);
if (propertyName !== undefined) {
return getStringLiteralType(unescapeLeadingUnderscores(propertyName));
}
if (isExpression(name)) {
return getRegularTypeOfLiteralType(checkExpression(name));
}
return neverType;
}
function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags, includeNonPublic?: boolean) {
if (includeNonPublic || !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) {
let type = getSymbolLinks(getLateBoundSymbol(prop)).nameType;
if (!type) {
const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName;
const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName | JsxAttributeName;
type = prop.escapedName === InternalSymbolName.Default ? getStringLiteralType("default") :
name && getLiteralTypeFromPropertyName(name) || (!isKnownSymbol(prop) ? getStringLiteralType(symbolName(prop)) : undefined);
}
@ -32647,7 +32660,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (getJsxNamespaceContainerForImplicitImport(node)) {
return true; // factory is implicitly jsx/jsxdev - assume it fits the bill, since we don't strongly look for the jsx/jsxs/jsxDEV factory APIs anywhere else (at least not yet)
}
const tagType = isJsxOpeningElement(node) || isJsxSelfClosingElement(node) && !isJsxIntrinsicTagName(node.tagName) ? checkExpression(node.tagName) : undefined;
const tagType = (isJsxOpeningElement(node) || isJsxSelfClosingElement(node)) && !(isJsxIntrinsicTagName(node.tagName) || isJsxNamespacedName(node.tagName)) ? checkExpression(node.tagName) : undefined;
if (!tagType) {
return true;
}

View File

@ -179,6 +179,7 @@ import {
getSyntheticLeadingComments,
getSyntheticTrailingComments,
getTextOfJSDocComment,
getTextOfJsxNamespacedName,
getTrailingCommentRanges,
getTrailingSemicolonDeferringWriter,
getTransformers,
@ -228,6 +229,7 @@ import {
isJSDocLikeText,
isJsonSourceFile,
isJsxClosingElement,
isJsxNamespacedName,
isJsxOpeningElement,
isKeyword,
isLet,
@ -2066,6 +2068,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return emitJsxSpreadAttribute(node as JsxSpreadAttribute);
case SyntaxKind.JsxExpression:
return emitJsxExpression(node as JsxExpression);
case SyntaxKind.JsxNamespacedName:
return emitJsxNamespacedName(node as JsxNamespacedName);
// Clauses
case SyntaxKind.CaseClause:
@ -2283,8 +2287,6 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return emitJsxSelfClosingElement(node as JsxSelfClosingElement);
case SyntaxKind.JsxFragment:
return emitJsxFragment(node as JsxFragment);
case SyntaxKind.JsxNamespacedName:
return emitJsxNamespacedName(node as JsxNamespacedName);
// Synthesized list
case SyntaxKind.SyntaxList:
@ -5528,7 +5530,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return node;
}
function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression, includeTrivia?: boolean): string {
function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression | JsxNamespacedName, includeTrivia?: boolean): string {
if (isGeneratedIdentifier(node) || isGeneratedPrivateIdentifier(node)) {
return generateName(node);
}
@ -5542,6 +5544,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return idText(node);
}
}
else if (isJsxNamespacedName(node)) {
if (!canUseSourceFile || getSourceFileOfNode(node) !== getOriginalNode(sourceFile)) {
return getTextOfJsxNamespacedName(node);
}
}
else {
Debug.assertNode(node, isLiteralExpression); // not strictly necessary
if (!canUseSourceFile) {
@ -5554,7 +5561,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) {
const textSourceNode = (node as StringLiteral).textSourceNode!;
if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode)) {
if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) || isJsxNamespacedName(textSourceNode)) {
const text = isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode(textSourceNode);
return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` :
neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(text)}"` :

View File

@ -147,6 +147,7 @@ import {
isJSDocNullableType,
isJSDocReturnTag,
isJSDocTypeTag,
isJsxNamespacedName,
isJsxOpeningElement,
isJsxOpeningFragment,
isKeyword,
@ -228,7 +229,6 @@ import {
JsxSelfClosingElement,
JsxSpreadAttribute,
JsxTagNameExpression,
JsxTagNamePropertyAccess,
JsxText,
JsxTokenSyntaxKind,
LabeledStatement,
@ -6122,11 +6122,15 @@ namespace Parser {
// primaryExpression in the form of an identifier and "this" keyword
// We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword
// We only want to consider "this" as a primaryExpression
let expression: JsxTagNameExpression = parseJsxTagName();
while (parseOptional(SyntaxKind.DotToken)) {
expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as JsxTagNamePropertyAccess;
const initialExpression = parseJsxTagName();
if (isJsxNamespacedName(initialExpression)) {
return initialExpression; // `a:b.c` is invalid syntax, don't even look for the `.` if we parse `a:b`, and let `parseAttribute` report "unexpected :" instead.
}
return expression;
let expression: PropertyAccessExpression | Identifier | ThisExpression = initialExpression;
while (parseOptional(SyntaxKind.DotToken)) {
expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos);
}
return expression as JsxTagNameExpression;
}
function parseJsxTagName(): Identifier | JsxNamespacedName | ThisExpression {

View File

@ -1722,11 +1722,9 @@ export type PropertyName = Identifier | StringLiteral | NumericLiteral | Compute
export type MemberName = Identifier | PrivateIdentifier;
export type DeclarationName =
| Identifier
| PrivateIdentifier
| PropertyName
| JsxAttributeName
| StringLiteralLike
| NumericLiteral
| ComputedPropertyName
| ElementAccessExpression
| BindingPattern
| EntityNameExpression;
@ -2332,7 +2330,7 @@ export interface LiteralTypeNode extends TypeNode {
export interface StringLiteral extends LiteralExpression, Declaration {
readonly kind: SyntaxKind.StringLiteral;
/** @internal */ readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier; // Allows a StringLiteral to get its text from another node (used by transforms).
/** @internal */ readonly textSourceNode?: Identifier | StringLiteralLike | NumericLiteral | PrivateIdentifier | JsxNamespacedName; // Allows a StringLiteral to get its text from another node (used by transforms).
/**
* Note: this is only set when synthesizing a node, not during parsing.
*
@ -2342,7 +2340,7 @@ export interface StringLiteral extends LiteralExpression, Declaration {
}
export type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral;
export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName;
export interface TemplateLiteralTypeNode extends TypeNode {
kind: SyntaxKind.TemplateLiteralType,
@ -3191,7 +3189,7 @@ export type JsxTagNameExpression =
;
export interface JsxTagNamePropertyAccess extends PropertyAccessExpression {
readonly expression: JsxTagNameExpression;
readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess;
}
export interface JsxAttributes extends PrimaryExpression, Declaration {
@ -3200,7 +3198,7 @@ export interface JsxAttributes extends PrimaryExpression, Declaration {
readonly parent: JsxOpeningLikeElement;
}
export interface JsxNamespacedName extends PrimaryExpression {
export interface JsxNamespacedName extends Node {
readonly kind: SyntaxKind.JsxNamespacedName;
readonly name: Identifier;
readonly namespace: Identifier;

View File

@ -293,6 +293,7 @@ import {
isJSDocTypeTag,
isJsxChild,
isJsxFragment,
isJsxNamespacedName,
isJsxOpeningLikeElement,
isJsxText,
isLeftHandSideExpression,
@ -2024,7 +2025,7 @@ export function isComputedNonLiteralName(name: PropertyName): boolean {
}
/** @internal */
export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String | undefined {
export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral | JsxAttributeName): __String | undefined {
switch (name.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.PrivateIdentifier:
@ -2036,13 +2037,15 @@ export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemp
case SyntaxKind.ComputedPropertyName:
if (isStringOrNumericLiteralLike(name.expression)) return escapeLeadingUnderscores(name.expression.text);
return undefined;
case SyntaxKind.JsxNamespacedName:
return getEscapedTextOfJsxNamespacedName(name);
default:
return Debug.assertNever(name);
}
}
/** @internal */
export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral): __String {
export function getTextOfPropertyName(name: PropertyName | NoSubstitutionTemplateLiteral | JsxAttributeName): __String {
return Debug.checkDefined(tryGetTextOfPropertyName(name));
}
@ -3074,7 +3077,7 @@ export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNam
}
/** @internal */
export function getInvokedExpression(node: CallLikeExpression): Expression {
export function getInvokedExpression(node: CallLikeExpression): Expression | JsxTagNameExpression {
switch (node.kind) {
case SyntaxKind.TaggedTemplateExpression:
return node.tag;
@ -4954,7 +4957,7 @@ export function isDynamicName(name: DeclarationName): boolean {
}
/** @internal */
export function getPropertyNameForPropertyNameNode(name: PropertyName): __String | undefined {
export function getPropertyNameForPropertyNameNode(name: PropertyName | JsxAttributeName): __String | undefined {
switch (name.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.PrivateIdentifier:
@ -4974,6 +4977,8 @@ export function getPropertyNameForPropertyNameNode(name: PropertyName): __String
return nameExpression.operand.text as __String;
}
return undefined;
case SyntaxKind.JsxNamespacedName:
return getEscapedTextOfJsxNamespacedName(name);
default:
return Debug.assertNever(name);
}
@ -4993,12 +4998,12 @@ export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral {
}
/** @internal */
export function getTextOfIdentifierOrLiteral(node: PropertyNameLiteral | PrivateIdentifier): string {
return isMemberName(node) ? idText(node) : node.text;
return isMemberName(node) ? idText(node) : isJsxNamespacedName(node) ? getTextOfJsxNamespacedName(node) : node.text;
}
/** @internal */
export function getEscapedTextOfIdentifierOrLiteral(node: PropertyNameLiteral): __String {
return isMemberName(node) ? node.escapedText : escapeLeadingUnderscores(node.text);
return isMemberName(node) ? node.escapedText : isJsxNamespacedName(node) ? getEscapedTextOfJsxNamespacedName(node) : escapeLeadingUnderscores(node.text);
}
/** @internal */
@ -7025,7 +7030,7 @@ export function isPropertyAccessEntityNameExpression(node: Node): node is Proper
}
/** @internal */
export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): string | undefined {
export function tryGetPropertyAccessOrIdentifierToString(expr: Expression | JsxTagNameExpression): string | undefined {
if (isPropertyAccessExpression(expr)) {
const baseStr = tryGetPropertyAccessOrIdentifierToString(expr.expression);
if (baseStr !== undefined) {
@ -7041,6 +7046,9 @@ export function tryGetPropertyAccessOrIdentifierToString(expr: Expression): stri
else if (isIdentifier(expr)) {
return unescapeLeadingUnderscores(expr.escapedText);
}
else if (isJsxNamespacedName(expr)) {
return getTextOfJsxNamespacedName(expr);
}
return undefined;
}

View File

@ -1941,7 +1941,6 @@ function isLeftHandSideExpressionKind(kind: SyntaxKind): boolean {
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxFragment:
case SyntaxKind.JsxNamespacedName:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ParenthesizedExpression:

View File

@ -55,6 +55,7 @@ import {
isTemplateSpan,
isTemplateTail,
isTransientSymbol,
JsxTagNameExpression,
last,
lastOrUndefined,
ListFormat,
@ -599,7 +600,7 @@ function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node,
return children[indexOfOpenerToken + 1];
}
function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): Expression {
function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): Expression | JsxTagNameExpression {
return invocation.kind === InvocationKind.Call ? getInvokedExpression(invocation.node) : invocation.called;
}

View File

@ -261,6 +261,7 @@ import {
JsTyping,
JsxEmit,
JsxOpeningLikeElement,
JsxTagNameExpression,
LabeledStatement,
LanguageServiceHost,
last,
@ -617,7 +618,7 @@ function selectTagNameOfJsxOpeningLikeElement(node: JsxOpeningLikeElement) {
return node.tagName;
}
function isCalleeWorker<T extends CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement>(node: Node, pred: (node: Node) => node is T, calleeSelector: (node: T) => Expression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) {
function isCalleeWorker<T extends CallExpression | NewExpression | TaggedTemplateExpression | Decorator | JsxOpeningLikeElement>(node: Node, pred: (node: Node) => node is T, calleeSelector: (node: T) => Expression | JsxTagNameExpression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) {
let target = includeElementAccess ? climbPastPropertyOrElementAccess(node) : climbPastPropertyAccess(node);
if (skipPastOuterExpressions) {
target = skipOuterExpressions(target);

View File

@ -4691,7 +4691,7 @@ declare namespace ts {
type EntityName = Identifier | QualifiedName;
type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier;
type MemberName = Identifier | PrivateIdentifier;
type DeclarationName = Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression;
type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression;
interface Declaration extends Node {
_declarationBrand: any;
}
@ -5038,7 +5038,7 @@ declare namespace ts {
readonly kind: SyntaxKind.StringLiteral;
}
type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral;
type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName;
interface TemplateLiteralTypeNode extends TypeNode {
kind: SyntaxKind.TemplateLiteralType;
readonly head: TemplateHead;
@ -5397,14 +5397,14 @@ declare namespace ts {
type JsxAttributeName = Identifier | JsxNamespacedName;
type JsxTagNameExpression = Identifier | ThisExpression | JsxTagNamePropertyAccess | JsxNamespacedName;
interface JsxTagNamePropertyAccess extends PropertyAccessExpression {
readonly expression: JsxTagNameExpression;
readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess;
}
interface JsxAttributes extends PrimaryExpression, Declaration {
readonly properties: NodeArray<JsxAttributeLike>;
readonly kind: SyntaxKind.JsxAttributes;
readonly parent: JsxOpeningLikeElement;
}
interface JsxNamespacedName extends PrimaryExpression {
interface JsxNamespacedName extends Node {
readonly kind: SyntaxKind.JsxNamespacedName;
readonly name: Identifier;
readonly namespace: Identifier;

View File

@ -644,7 +644,7 @@ declare namespace ts {
type EntityName = Identifier | QualifiedName;
type PropertyName = Identifier | StringLiteral | NumericLiteral | ComputedPropertyName | PrivateIdentifier;
type MemberName = Identifier | PrivateIdentifier;
type DeclarationName = Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | ElementAccessExpression | BindingPattern | EntityNameExpression;
type DeclarationName = PropertyName | JsxAttributeName | StringLiteralLike | ElementAccessExpression | BindingPattern | EntityNameExpression;
interface Declaration extends Node {
_declarationBrand: any;
}
@ -991,7 +991,7 @@ declare namespace ts {
readonly kind: SyntaxKind.StringLiteral;
}
type StringLiteralLike = StringLiteral | NoSubstitutionTemplateLiteral;
type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral;
type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral | JsxNamespacedName;
interface TemplateLiteralTypeNode extends TypeNode {
kind: SyntaxKind.TemplateLiteralType;
readonly head: TemplateHead;
@ -1350,14 +1350,14 @@ declare namespace ts {
type JsxAttributeName = Identifier | JsxNamespacedName;
type JsxTagNameExpression = Identifier | ThisExpression | JsxTagNamePropertyAccess | JsxNamespacedName;
interface JsxTagNamePropertyAccess extends PropertyAccessExpression {
readonly expression: JsxTagNameExpression;
readonly expression: Identifier | ThisExpression | JsxTagNamePropertyAccess;
}
interface JsxAttributes extends PrimaryExpression, Declaration {
readonly properties: NodeArray<JsxAttributeLike>;
readonly kind: SyntaxKind.JsxAttributes;
readonly parent: JsxOpeningLikeElement;
}
interface JsxNamespacedName extends PrimaryExpression {
interface JsxNamespacedName extends Node {
readonly kind: SyntaxKind.JsxNamespacedName;
readonly name: Identifier;
readonly namespace: Identifier;

View File

@ -1,7 +1,10 @@
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,2): error TS2633: JSX property access expressions cannot include JSX namespace names
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,5): error TS1003: Identifier expected.
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,13): error TS1005: '>' expected.
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,14): error TS2304: Cannot find name 'x'.
tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,16): error TS1109: Expression expected.
==== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx (1 errors) ====
==== tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx (4 errors) ====
declare namespace JSX {
interface IntrinsicElements {
'this:b': any;
@ -14,6 +17,12 @@ tests/cases/conformance/jsx/checkJsxNamespaceNamesQuestionableForms.tsx(12,2): e
<a:b></a:b>;
<b:c.x></b:c.x>;
~~~
!!! error TS2633: JSX property access expressions cannot include JSX namespace names
~
!!! error TS1003: Identifier expected.
~
!!! error TS1005: '>' expected.
~
!!! error TS2304: Cannot find name 'x'.
~
!!! error TS1109: Expression expected.
<this:b></this:b>;

View File

@ -15,5 +15,6 @@ declare namespace JSX {
//// [checkJsxNamespaceNamesQuestionableForms.jsx]
<a:b></a:b>;
<b:c.x></b:c.x>;
<b:c x></b:c>;
x > ;
<this:b></this:b>;

View File

@ -22,4 +22,6 @@ declare namespace JSX {
<a:b></a:b>;
<b:c.x></b:c.x>;
>x : Symbol(x, Decl(checkJsxNamespaceNamesQuestionableForms.tsx, 11, 5))
<this:b></this:b>;

View File

@ -24,15 +24,15 @@ declare namespace JSX {
>b : any
<b:c.x></b:c.x>;
><b:c.x></b:c.x> : any
>b:c.x : any
><b:c.x></b:c : any
>b : any
>c : any
>x : any
>b:c.x : any
>x : true
>b : any
>c : any
>x> : boolean
>x : any
> : any
<this:b></this:b>;
><this:b></this:b> : any

View File

@ -74,7 +74,10 @@ tests/cases/conformance/jsx/5.tsx(1,5): error TS1005: '</' expected.
tests/cases/conformance/jsx/6.tsx(1,6): error TS17002: Expected corresponding JSX closing tag for 'a'.
tests/cases/conformance/jsx/7.tsx(1,13): error TS1002: Unterminated string literal.
tests/cases/conformance/jsx/8.tsx(1,8): error TS17002: Expected corresponding JSX closing tag for 'a:b'.
tests/cases/conformance/jsx/9.tsx(1,2): error TS2633: JSX property access expressions cannot include JSX namespace names
tests/cases/conformance/jsx/9.tsx(1,5): error TS1003: Identifier expected.
tests/cases/conformance/jsx/9.tsx(1,13): error TS1005: '>' expected.
tests/cases/conformance/jsx/9.tsx(1,14): error TS2304: Cannot find name 'c'.
tests/cases/conformance/jsx/9.tsx(1,16): error TS1109: Expression expected.
==== tests/cases/conformance/jsx/1.tsx (3 errors) ====
@ -125,10 +128,16 @@ tests/cases/conformance/jsx/9.tsx(1,2): error TS2633: JSX property access expres
<a:b></b>;
~
!!! error TS17002: Expected corresponding JSX closing tag for 'a:b'.
==== tests/cases/conformance/jsx/9.tsx (1 errors) ====
==== tests/cases/conformance/jsx/9.tsx (4 errors) ====
<a:b.c></a:b.c>;
~~~
!!! error TS2633: JSX property access expressions cannot include JSX namespace names
~
!!! error TS1003: Identifier expected.
~
!!! error TS1005: '>' expected.
~
!!! error TS2304: Cannot find name 'c'.
~
!!! error TS1109: Expression expected.
==== tests/cases/conformance/jsx/10.tsx (6 errors) ====
<a.b:c></a.b:c>;
~

View File

@ -92,7 +92,8 @@ a / > ;
//// [8.jsx]
<a:b></b>;
//// [9.jsx]
<a:b.c></a:b.c>;
<a:b c></a:b>;
c > ;
//// [10.jsx]
<a.b c></a.b>;
c > ;

View File

@ -28,8 +28,9 @@ declare var React: any;
<a:b></b>;
=== tests/cases/conformance/jsx/9.tsx ===
<a:b.c></a:b.c>;
>c : Symbol(c, Decl(9.tsx, 0, 5))
=== tests/cases/conformance/jsx/10.tsx ===
<a.b:c></a.b:c>;
>c : Symbol(c, Decl(10.tsx, 0, 5))

View File

@ -58,15 +58,15 @@ declare var React: any;
=== tests/cases/conformance/jsx/9.tsx ===
<a:b.c></a:b.c>;
><a:b.c></a:b.c> : any
>a:b.c : any
><a:b.c></a:b : any
>a : any
>b : any
>c : any
>a:b.c : any
>c : true
>a : any
>b : any
>c> : boolean
>c : any
> : any
=== tests/cases/conformance/jsx/10.tsx ===
<a.b:c></a.b:c>;

View File

@ -0,0 +1,16 @@
//// [jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx]
/// <reference path="/.lib/react16.d.ts" />
declare module "react" {
interface Attributes {
[key: `do-${string}`]: Function;
"ns:thing"?: string;
}
}
export const tag = <div ns:thing="a"/>
//// [jsxNamespacedNameNotComparedToNonMatchingIndexSignature.js]
import { jsx as _jsx } from "react/jsx-runtime";
/// <reference path="react16.d.ts" />
export const tag = _jsx("div", { "ns:thing": "a" });

View File

@ -0,0 +1,23 @@
=== tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx ===
/// <reference path="react16.d.ts" />
declare module "react" {
>"react" : Symbol(React, Decl(react16.d.ts, 110, 19), Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 0, 0))
interface Attributes {
>Attributes : Symbol(Attributes, Decl(react16.d.ts, 128, 34), Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 2, 24))
[key: `do-${string}`]: Function;
>key : Symbol(key, Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 4, 9))
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
"ns:thing"?: string;
>"ns:thing" : Symbol(Attributes["ns:thing"], Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 4, 40))
}
}
export const tag = <div ns:thing="a"/>
>tag : Symbol(tag, Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 9, 12))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react16.d.ts, 2546, 114))
>ns:thing : Symbol(ns:thing, Decl(jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx, 9, 23))

View File

@ -0,0 +1,23 @@
=== tests/cases/compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx ===
/// <reference path="react16.d.ts" />
declare module "react" {
>"react" : typeof import("react")
interface Attributes {
[key: `do-${string}`]: Function;
>key : `do-${string}`
"ns:thing"?: string;
>"ns:thing" : string
}
}
export const tag = <div ns:thing="a"/>
>tag : JSX.Element
><div ns:thing="a"/> : JSX.Element
>div : any
>ns:thing : string
>ns : error
>thing : error

View File

@ -0,0 +1,12 @@
// @jsx: react-jsx
// @target: esnext
/// <reference path="/.lib/react16.d.ts" />
declare module "react" {
interface Attributes {
[key: `do-${string}`]: Function;
"ns:thing"?: string;
}
}
export const tag = <div ns:thing="a"/>