mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
feat(7411): Resolve intrinsics elements by JSX namespaced tag names (#53799)
This commit is contained in:
parent
f8b3ea7972
commit
378ffa4bc9
@ -89,6 +89,7 @@ import {
|
||||
getEnclosingBlockScopeContainer,
|
||||
getErrorSpanForNode,
|
||||
getEscapedTextOfIdentifierOrLiteral,
|
||||
getEscapedTextOfJsxAttributeName,
|
||||
getExpandoInitializer,
|
||||
getHostSignatureFromJSDoc,
|
||||
getImmediatelyInvokedFunctionExpression,
|
||||
@ -171,6 +172,7 @@ import {
|
||||
isJSDocTemplateTag,
|
||||
isJSDocTypeAlias,
|
||||
isJsonSourceFile,
|
||||
isJsxNamespacedName,
|
||||
isLeftHandSideExpression,
|
||||
isLogicalOrCoalescingAssignmentExpression,
|
||||
isLogicalOrCoalescingAssignmentOperator,
|
||||
@ -679,6 +681,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
const containingClassSymbol = containingClass.symbol;
|
||||
return getSymbolNameForPrivateIdentifier(containingClassSymbol, name.escapedText);
|
||||
}
|
||||
if (isJsxNamespacedName(name)) {
|
||||
return getEscapedTextOfJsxAttributeName(name);
|
||||
}
|
||||
return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined;
|
||||
}
|
||||
switch (node.kind) {
|
||||
|
||||
@ -276,6 +276,7 @@ import {
|
||||
getErrorSpanForNode,
|
||||
getEscapedTextOfIdentifierOrLiteral,
|
||||
getEscapedTextOfJsxAttributeName,
|
||||
getEscapedTextOfJsxNamespacedName,
|
||||
getESModuleInterop,
|
||||
getExpandoInitializer,
|
||||
getExportAssignmentExpression,
|
||||
@ -429,6 +430,7 @@ import {
|
||||
InternalSymbolName,
|
||||
IntersectionType,
|
||||
IntersectionTypeNode,
|
||||
intrinsicTagNameToString,
|
||||
IntrinsicType,
|
||||
introducesArgumentsExoticObject,
|
||||
isAccessExpression,
|
||||
@ -782,6 +784,7 @@ import {
|
||||
JsxExpression,
|
||||
JsxFlags,
|
||||
JsxFragment,
|
||||
JsxNamespacedName,
|
||||
JsxOpeningElement,
|
||||
JsxOpeningFragment,
|
||||
JsxOpeningLikeElement,
|
||||
@ -29597,7 +29600,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function getStaticTypeOfReferencedJsxConstructor(context: JsxOpeningLikeElement) {
|
||||
if (isJsxIntrinsicIdentifier(context.tagName)) {
|
||||
if (isJsxIntrinsicTagName(context.tagName)) {
|
||||
const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(context);
|
||||
const fakeSignature = createSignatureForJSXIntrinsic(context, result);
|
||||
return getOrCreateTypeFromSignature(fakeSignature);
|
||||
@ -30317,7 +30320,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement);
|
||||
|
||||
// Perform resolution on the closing tag so that rename/go to definition/etc work
|
||||
if (isJsxIntrinsicIdentifier(node.closingElement.tagName)) {
|
||||
if (isJsxIntrinsicTagName(node.closingElement.tagName)) {
|
||||
getIntrinsicTagSymbol(node.closingElement);
|
||||
}
|
||||
else {
|
||||
@ -30357,8 +30360,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
/**
|
||||
* Returns true iff React would emit this tag name as a string rather than an identifier or qualified name
|
||||
*/
|
||||
function isJsxIntrinsicIdentifier(tagName: JsxTagNameExpression): tagName is Identifier {
|
||||
return tagName.kind === SyntaxKind.Identifier && isIntrinsicJsxName(tagName.escapedText);
|
||||
function isJsxIntrinsicTagName(tagName: Node): tagName is Identifier | JsxNamespacedName {
|
||||
return isIdentifier(tagName) && isIntrinsicJsxName(tagName.escapedText) || isJsxNamespacedName(tagName);
|
||||
}
|
||||
|
||||
function checkJsxAttribute(node: JsxAttribute, checkMode?: CheckMode) {
|
||||
@ -30563,8 +30566,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, node);
|
||||
if (!isErrorType(intrinsicElementsType)) {
|
||||
// Property case
|
||||
if (!isIdentifier(node.tagName)) return Debug.fail();
|
||||
const intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText);
|
||||
if (!isIdentifier(node.tagName) && !isJsxNamespacedName(node.tagName)) return Debug.fail();
|
||||
const intrinsicProp = getPropertyOfType(intrinsicElementsType, isJsxNamespacedName(node.tagName) ? getEscapedTextOfJsxNamespacedName(node.tagName) : node.tagName.escapedText);
|
||||
if (intrinsicProp) {
|
||||
links.jsxFlags |= JsxFlags.IntrinsicNamedElement;
|
||||
return links.resolvedSymbol = intrinsicProp;
|
||||
@ -30578,7 +30581,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
// Wasn't found
|
||||
error(node, Diagnostics.Property_0_does_not_exist_on_type_1, idText(node.tagName), "JSX." + JsxNames.IntrinsicElements);
|
||||
error(node, Diagnostics.Property_0_does_not_exist_on_type_1, intrinsicTagNameToString(node.tagName), "JSX." + JsxNames.IntrinsicElements);
|
||||
return links.resolvedSymbol = unknownSymbol;
|
||||
}
|
||||
else {
|
||||
@ -30787,7 +30790,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
* @param node an intrinsic JSX opening-like element
|
||||
*/
|
||||
function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node: JsxOpeningLikeElement): Type {
|
||||
Debug.assert(isJsxIntrinsicIdentifier(node.tagName));
|
||||
Debug.assert(isJsxIntrinsicTagName(node.tagName));
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedJsxElementAttributesType) {
|
||||
const symbol = getIntrinsicTagSymbol(node);
|
||||
@ -30900,8 +30903,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const elementTypeConstraint = getJsxElementTypeTypeAt(jsxOpeningLikeNode);
|
||||
if (elementTypeConstraint !== undefined) {
|
||||
const tagName = jsxOpeningLikeNode.tagName;
|
||||
const tagType = isJsxIntrinsicIdentifier(tagName)
|
||||
? getStringLiteralType(unescapeLeadingUnderscores(tagName.escapedText))
|
||||
const tagType = isJsxIntrinsicTagName(tagName)
|
||||
? getStringLiteralType(intrinsicTagNameToString(tagName))
|
||||
: checkExpression(tagName);
|
||||
checkTypeRelatedTo(tagType, elementTypeConstraint, assignableRelation, tagName, Diagnostics.Its_type_0_is_not_a_valid_JSX_element_type, () => {
|
||||
const componentName = getTextOfNode(tagName);
|
||||
@ -32521,7 +32524,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function getJsxReferenceKind(node: JsxOpeningLikeElement): JsxReferenceKind {
|
||||
if (isJsxIntrinsicIdentifier(node.tagName)) {
|
||||
if (isJsxIntrinsicTagName(node.tagName)) {
|
||||
return JsxReferenceKind.Mixed;
|
||||
}
|
||||
const tagType = getApparentType(checkExpression(node.tagName));
|
||||
@ -32568,7 +32571,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) && !isJsxIntrinsicIdentifier(node.tagName) ? checkExpression(node.tagName) : undefined;
|
||||
const tagType = isJsxOpeningElement(node) || isJsxSelfClosingElement(node) && !isJsxIntrinsicTagName(node.tagName) ? checkExpression(node.tagName) : undefined;
|
||||
if (!tagType) {
|
||||
return true;
|
||||
}
|
||||
@ -33972,7 +33975,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature {
|
||||
if (isJsxIntrinsicIdentifier(node.tagName)) {
|
||||
if (isJsxIntrinsicTagName(node.tagName)) {
|
||||
const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node);
|
||||
const fakeSignature = createSignatureForJSXIntrinsic(node, result);
|
||||
checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*inferenceContext*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes);
|
||||
@ -45438,7 +45441,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const isJSDoc = findAncestor(name, or(isJSDocLinkLike, isJSDocNameReference, isJSDocMemberName));
|
||||
const meaning = isJSDoc ? SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value : SymbolFlags.Value;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
if (isJSXTagName(name) && isJsxIntrinsicIdentifier(name)) {
|
||||
if (isJSXTagName(name) && isJsxIntrinsicTagName(name)) {
|
||||
const symbol = getIntrinsicTagSymbol(name.parent as JsxOpeningLikeElement);
|
||||
return symbol === unknownSymbol ? undefined : symbol;
|
||||
}
|
||||
@ -45685,6 +45688,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return isMetaProperty(node.parent) ? checkMetaPropertyKeyword(node.parent).symbol : undefined;
|
||||
case SyntaxKind.MetaProperty:
|
||||
return checkExpression(node as Expression).symbol;
|
||||
case SyntaxKind.JsxNamespacedName:
|
||||
if (isJSXTagName(node) && isJsxIntrinsicTagName(node)) {
|
||||
const symbol = getIntrinsicTagSymbol(node.parent as JsxOpeningLikeElement);
|
||||
return symbol === unknownSymbol ? undefined : symbol;
|
||||
}
|
||||
// falls through
|
||||
|
||||
default:
|
||||
return undefined;
|
||||
|
||||
@ -361,6 +361,7 @@ import {
|
||||
JsxElement,
|
||||
JsxEmit,
|
||||
JsxFragment,
|
||||
JsxNamespacedName,
|
||||
JsxOpeningElement,
|
||||
JsxOpeningLikeElement,
|
||||
JsxSelfClosingElement,
|
||||
@ -5828,7 +5829,7 @@ function isQuoteOrBacktick(charCode: number) {
|
||||
/** @internal */
|
||||
export function isIntrinsicJsxName(name: __String | string) {
|
||||
const ch = (name as string).charCodeAt(0);
|
||||
return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || stringContains((name as string), "-") || stringContains((name as string), ":");
|
||||
return (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || stringContains((name as string), "-");
|
||||
}
|
||||
|
||||
const indentStrings: string[] = ["", " "];
|
||||
@ -10177,12 +10178,12 @@ export function tryGetJSDocSatisfiesTypeNode(node: Node) {
|
||||
|
||||
/** @internal */
|
||||
export function getEscapedTextOfJsxAttributeName(node: JsxAttributeName): __String {
|
||||
return isIdentifier(node) ? node.escapedText : `${node.namespace.escapedText}:${idText(node.name)}` as __String;
|
||||
return isIdentifier(node) ? node.escapedText : getEscapedTextOfJsxNamespacedName(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getTextOfJsxAttributeName(node: JsxAttributeName): string {
|
||||
return isIdentifier(node) ? idText(node) : `${idText(node.namespace)}:${idText(node.name)}`;
|
||||
return isIdentifier(node) ? idText(node) : getTextOfJsxNamespacedName(node);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@ -10191,3 +10192,18 @@ export function isJsxAttributeName(node: Node): node is JsxAttributeName {
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.JsxNamespacedName;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getEscapedTextOfJsxNamespacedName(node: JsxNamespacedName): __String {
|
||||
return `${node.namespace.escapedText}:${idText(node.name)}` as __String;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getTextOfJsxNamespacedName(node: JsxNamespacedName) {
|
||||
return `${idText(node.namespace)}:${idText(node.name)}`;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function intrinsicTagNameToString(node: Identifier | JsxNamespacedName) {
|
||||
return isIdentifier(node) ? idText(node) : getTextOfJsxNamespacedName(node);
|
||||
}
|
||||
|
||||
@ -156,6 +156,7 @@ import {
|
||||
isJsxClosingElement,
|
||||
isJsxElement,
|
||||
isJsxFragment,
|
||||
isJsxNamespacedName,
|
||||
isJsxOpeningElement,
|
||||
isJsxOpeningFragment,
|
||||
isJsxText,
|
||||
@ -2064,6 +2065,9 @@ export function createLanguageService(
|
||||
if (isImportMeta(node.parent) && node.parent.name === node) {
|
||||
return node.parent;
|
||||
}
|
||||
if (isJsxNamespacedName(node.parent)) {
|
||||
return node.parent;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@ -34,9 +34,11 @@ tests/cases/compiler/jsxElementType.tsx(91,2): error TS2786: 'ReactNativeFlatLis
|
||||
tests/cases/compiler/jsxElementType.tsx(95,11): error TS2322: Type '{}' is not assignable to type 'LibraryManagedAttributes<T, {}>'.
|
||||
tests/cases/compiler/jsxElementType.tsx(98,2): error TS2304: Cannot find name 'Unresolved'.
|
||||
tests/cases/compiler/jsxElementType.tsx(99,2): error TS2304: Cannot find name 'Unresolved'.
|
||||
tests/cases/compiler/jsxElementType.tsx(109,19): error TS2322: Type '{ a: string; b: string; }' is not assignable to type '{ a: string; }'.
|
||||
Property 'b' does not exist on type '{ a: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/jsxElementType.tsx (18 errors) ====
|
||||
==== tests/cases/compiler/jsxElementType.tsx (19 errors) ====
|
||||
/// <reference path="/.lib/react16.d.ts" />
|
||||
import * as React from "react";
|
||||
|
||||
@ -197,4 +199,17 @@ tests/cases/compiler/jsxElementType.tsx(99,2): error TS2304: Cannot find name 'U
|
||||
<Unresolved foo="abc" />;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'Unresolved'.
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
['a:b']: { a: string };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<a:b a="accepted" b="rejected" />;
|
||||
~
|
||||
!!! error TS2322: Type '{ a: string; b: string; }' is not assignable to type '{ a: string; }'.
|
||||
!!! error TS2322: Property 'b' does not exist on type '{ a: string; }'.
|
||||
|
||||
@ -98,6 +98,16 @@ function f1<T extends (props: {}) => React.ReactElement<any>>(Component: T) {
|
||||
|
||||
<Unresolved />;
|
||||
<Unresolved foo="abc" />;
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
['a:b']: { a: string };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<a:b a="accepted" b="rejected" />;
|
||||
|
||||
|
||||
//// [jsxElementType.js]
|
||||
@ -231,3 +241,4 @@ function f1(Component) {
|
||||
}
|
||||
React.createElement(Unresolved, null);
|
||||
React.createElement(Unresolved, { foo: "abc" });
|
||||
React.createElement("a:b", { a: "accepted", b: "rejected" });
|
||||
|
||||
@ -49,17 +49,17 @@ type NewReactJSXElementConstructor<P> =
|
||||
>P : Symbol(P, Decl(jsxElementType.tsx, 16, 35))
|
||||
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(jsxElementType.tsx, 18, 48))
|
||||
>global : Symbol(global, Decl(jsxElementType.tsx, 18, 48), Decl(jsxElementType.tsx, 98, 25))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementType.tsx, 20, 16))
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementType.tsx, 20, 16), Decl(jsxElementType.tsx, 100, 16))
|
||||
|
||||
type ElementType = string | NewReactJSXElementConstructor<any>;
|
||||
>ElementType : Symbol(ElementType, Decl(jsxElementType.tsx, 21, 17))
|
||||
>NewReactJSXElementConstructor : Symbol(NewReactJSXElementConstructor, Decl(jsxElementType.tsx, 13, 30))
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react16.d.ts, 2514, 86), Decl(jsxElementType.tsx, 22, 67))
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react16.d.ts, 2514, 86), Decl(jsxElementType.tsx, 22, 67), Decl(jsxElementType.tsx, 101, 19))
|
||||
|
||||
['my-custom-element']: React.DOMAttributes<unknown>;
|
||||
>['my-custom-element'] : Symbol(IntrinsicElements['my-custom-element'], Decl(jsxElementType.tsx, 23, 33))
|
||||
@ -272,3 +272,24 @@ function f1<T extends (props: {}) => React.ReactElement<any>>(Component: T) {
|
||||
<Unresolved foo="abc" />;
|
||||
>foo : Symbol(foo, Decl(jsxElementType.tsx, 98, 11))
|
||||
|
||||
declare global {
|
||||
>global : Symbol(global, Decl(jsxElementType.tsx, 18, 48), Decl(jsxElementType.tsx, 98, 25))
|
||||
|
||||
namespace JSX {
|
||||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12), Decl(jsxElementType.tsx, 20, 16), Decl(jsxElementType.tsx, 100, 16))
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(react16.d.ts, 2514, 86), Decl(jsxElementType.tsx, 22, 67), Decl(jsxElementType.tsx, 101, 19))
|
||||
|
||||
['a:b']: { a: string };
|
||||
>['a:b'] : Symbol(IntrinsicElements['a:b'], Decl(jsxElementType.tsx, 102, 35))
|
||||
>'a:b' : Symbol(IntrinsicElements['a:b'], Decl(jsxElementType.tsx, 102, 35))
|
||||
>a : Symbol(a, Decl(jsxElementType.tsx, 103, 20))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<a:b a="accepted" b="rejected" />;
|
||||
>a : Symbol(a, Decl(jsxElementType.tsx, 108, 4))
|
||||
>b : Symbol(b, Decl(jsxElementType.tsx, 108, 17))
|
||||
|
||||
|
||||
@ -290,3 +290,23 @@ function f1<T extends (props: {}) => React.ReactElement<any>>(Component: T) {
|
||||
>Unresolved : any
|
||||
>foo : string
|
||||
|
||||
declare global {
|
||||
>global : any
|
||||
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
['a:b']: { a: string };
|
||||
>['a:b'] : { a: string; }
|
||||
>'a:b' : "a:b"
|
||||
>a : string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<a:b a="accepted" b="rejected" />;
|
||||
><a:b a="accepted" b="rejected" /> : JSX.Element
|
||||
>a : any
|
||||
>b : any
|
||||
>a : string
|
||||
>b : string
|
||||
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
tests/cases/compiler/jsxNamespacePrefixIntrinsics.tsx(15,18): error TS2339: Property 'element' does not exist on type 'JSX.IntrinsicElements'.
|
||||
tests/cases/compiler/jsxNamespacePrefixIntrinsics.tsx(16,30): error TS2322: Type '{ attribute: string; }' is not assignable to type '{ "ns:attribute": string; }'.
|
||||
Property 'attribute' does not exist on type '{ "ns:attribute": string; }'. Did you mean '"ns:attribute"'?
|
||||
tests/cases/compiler/jsxNamespacePrefixIntrinsics.tsx(17,30): error TS2322: Type '{ "ns:invalid": string; }' is not assignable to type '{ "ns:attribute": string; }'.
|
||||
Property 'ns:invalid' does not exist on type '{ "ns:attribute": string; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/jsxNamespacePrefixIntrinsics.tsx (1 errors) ====
|
||||
==== tests/cases/compiler/jsxNamespacePrefixIntrinsics.tsx (3 errors) ====
|
||||
declare namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
"ns:element": {
|
||||
@ -20,5 +24,11 @@ tests/cases/compiler/jsxNamespacePrefixIntrinsics.tsx(15,18): error TS2339: Prop
|
||||
~~~~~~~~~~~
|
||||
!!! error TS2339: Property 'element' does not exist on type 'JSX.IntrinsicElements'.
|
||||
const invalid2 = <ns:element attribute="nope" />;
|
||||
~~~~~~~~~
|
||||
!!! error TS2322: Type '{ attribute: string; }' is not assignable to type '{ "ns:attribute": string; }'.
|
||||
!!! error TS2322: Property 'attribute' does not exist on type '{ "ns:attribute": string; }'. Did you mean '"ns:attribute"'?
|
||||
const invalid3 = <ns:element ns:invalid="nope" />;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ "ns:invalid": string; }' is not assignable to type '{ "ns:attribute": string; }'.
|
||||
!!! error TS2322: Property 'ns:invalid' does not exist on type '{ "ns:attribute": string; }'.
|
||||
|
||||
117
tests/baselines/reference/quickInfoOnJsxNamespacedName.baseline
Normal file
117
tests/baselines/reference/quickInfoOnJsxNamespacedName.baseline
Normal file
@ -0,0 +1,117 @@
|
||||
=== /a.tsx ===
|
||||
// <a:b a="accepted" b="rejected" />;
|
||||
// ^^^
|
||||
// | ----------------------------------------------------------------------
|
||||
// | (property) JSX.IntrinsicElements['a:b']: {
|
||||
// | a: string;
|
||||
// | }
|
||||
// | ----------------------------------------------------------------------
|
||||
|
||||
[
|
||||
{
|
||||
"marker": {
|
||||
"fileName": "/a.tsx",
|
||||
"position": 1,
|
||||
"name": ""
|
||||
},
|
||||
"item": {
|
||||
"kind": "property",
|
||||
"kindModifiers": "declare",
|
||||
"textSpan": {
|
||||
"start": 1,
|
||||
"length": 3
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "(",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "property",
|
||||
"kind": "text"
|
||||
},
|
||||
{
|
||||
"text": ")",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "JSX",
|
||||
"kind": "moduleName"
|
||||
},
|
||||
{
|
||||
"text": ".",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "IntrinsicElements",
|
||||
"kind": "interfaceName"
|
||||
},
|
||||
{
|
||||
"text": "[",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "'a:b'",
|
||||
"kind": "stringLiteral"
|
||||
},
|
||||
{
|
||||
"text": "]",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "{",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "a",
|
||||
"kind": "propertyName"
|
||||
},
|
||||
{
|
||||
"text": ":",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": " ",
|
||||
"kind": "space"
|
||||
},
|
||||
{
|
||||
"text": "string",
|
||||
"kind": "keyword"
|
||||
},
|
||||
{
|
||||
"text": ";",
|
||||
"kind": "punctuation"
|
||||
},
|
||||
{
|
||||
"text": "\n",
|
||||
"kind": "lineBreak"
|
||||
},
|
||||
{
|
||||
"text": "}",
|
||||
"kind": "punctuation"
|
||||
}
|
||||
],
|
||||
"documentation": []
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -99,3 +99,13 @@ function f1<T extends (props: {}) => React.ReactElement<any>>(Component: T) {
|
||||
|
||||
<Unresolved />;
|
||||
<Unresolved foo="abc" />;
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
['a:b']: { a: string };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<a:b a="accepted" b="rejected" />;
|
||||
|
||||
13
tests/cases/fourslash/quickInfoOnJsxNamespacedName.ts
Normal file
13
tests/cases/fourslash/quickInfoOnJsxNamespacedName.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @jsx: react
|
||||
|
||||
// @Filename: /types.d.ts
|
||||
////declare namespace JSX {
|
||||
//// interface IntrinsicElements { ['a:b']: { a: string }; }
|
||||
////}
|
||||
|
||||
// @filename: /a.tsx
|
||||
////</**/a:b a="accepted" b="rejected" />;
|
||||
|
||||
verify.baselineQuickInfo();
|
||||
Loading…
x
Reference in New Issue
Block a user