diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 692b6ea848bf0..135c52eb50120 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8797,18 +8797,20 @@ namespace ts { if (!elemClassType || !isTypeAssignableTo(elemInstanceType, elemClassType)) { // Is this is a stateless function component? See if its single signature's return type is // assignable to the JSX Element Type - const elemType = checkExpression(node.tagName); - const callSignatures = elemType && getSignaturesOfType(elemType, SignatureKind.Call); - const callSignature = callSignatures && callSignatures.length > 0 && callSignatures[0]; - const callReturnType = callSignature && getReturnTypeOfSignature(callSignature); - let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0])); - if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) { - // Intersect in JSX.IntrinsicAttributes if it exists - const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes); - if (intrinsicAttributes !== unknownType) { - paramType = intersectTypes(intrinsicAttributes, paramType); + if (jsxElementType) { + const elemType = checkExpression(node.tagName); + const callSignatures = elemType && getSignaturesOfType(elemType, SignatureKind.Call); + const callSignature = callSignatures && callSignatures.length > 0 && callSignatures[0]; + const callReturnType = callSignature && getReturnTypeOfSignature(callSignature); + let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0])); + if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) { + // Intersect in JSX.IntrinsicAttributes if it exists + const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes); + if (intrinsicAttributes !== unknownType) { + paramType = intersectTypes(intrinsicAttributes, paramType); + } + return links.resolvedJsxType = paramType; } - return links.resolvedJsxType = paramType; } } diff --git a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt index b5d4e01b67782..32b86e455d22c 100644 --- a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt +++ b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.errors.txt @@ -1,15 +1,18 @@ -tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(13,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. +tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(16,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. Type '"f"' is not assignable to type '"C"'. -tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(14,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. +tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx(17,15): error TS2322: Type '"f"' is not assignable to type '"A" | "B" | "C"'. Type '"f"' is not assignable to type '"C"'. ==== tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx (2 errors) ==== namespace JSX { - interface IntrinsicElements { + export interface IntrinsicElements { span: {}; } + export interface Element { + something?: any; + } } const FooComponent = (props: { foo: "A" | "B" | "C" }) => {props.foo}; diff --git a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.js b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.js index c21247c283595..d1b2ebf5ae544 100644 --- a/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.js +++ b/tests/baselines/reference/contextuallyTypedStringLiteralsInJsxAttributes01.js @@ -1,9 +1,12 @@ //// [contextuallyTypedStringLiteralsInJsxAttributes01.tsx] namespace JSX { - interface IntrinsicElements { + export interface IntrinsicElements { span: {}; } + export interface Element { + something?: any; + } } const FooComponent = (props: { foo: "A" | "B" | "C" }) => {props.foo}; @@ -24,7 +27,13 @@ var FooComponent = function (props) { return {props.foo}; }; //// [contextuallyTypedStringLiteralsInJsxAttributes01.d.ts] declare namespace JSX { + interface IntrinsicElements { + span: {}; + } + interface Element { + something?: any; + } } declare const FooComponent: (props: { foo: "A" | "B" | "C"; -}) => any; +}) => JSX.Element; diff --git a/tests/baselines/reference/tsxAttributeResolution13.js b/tests/baselines/reference/tsxAttributeResolution13.js new file mode 100644 index 0000000000000..e6c942eb926c2 --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution13.js @@ -0,0 +1,9 @@ +//// [test.tsx] + +function Test() { } + + + +//// [test.jsx] +function Test() { } +; diff --git a/tests/baselines/reference/tsxAttributeResolution13.symbols b/tests/baselines/reference/tsxAttributeResolution13.symbols new file mode 100644 index 0000000000000..a913e50969cc5 --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution13.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsx/test.tsx === + +function Test() { } +>Test : Symbol(Test, Decl(test.tsx, 0, 0)) + + +>Test : Symbol(Test, Decl(test.tsx, 0, 0)) +>Test : Symbol(Test, Decl(test.tsx, 0, 0)) + diff --git a/tests/baselines/reference/tsxAttributeResolution13.types b/tests/baselines/reference/tsxAttributeResolution13.types new file mode 100644 index 0000000000000..f0435b8081265 --- /dev/null +++ b/tests/baselines/reference/tsxAttributeResolution13.types @@ -0,0 +1,10 @@ +=== tests/cases/conformance/jsx/test.tsx === + +function Test() { } +>Test : () => void + + +> : any +>Test : any +>Test : any + diff --git a/tests/cases/conformance/jsx/tsxAttributeResolution13.tsx b/tests/cases/conformance/jsx/tsxAttributeResolution13.tsx new file mode 100644 index 0000000000000..1b5937a7db232 --- /dev/null +++ b/tests/cases/conformance/jsx/tsxAttributeResolution13.tsx @@ -0,0 +1,5 @@ +//@jsx: preserve + +//@filename: test.tsx +function Test() { } + diff --git a/tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx b/tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx index ce6f4b7ac2f90..2235961086f7b 100644 --- a/tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx +++ b/tests/cases/conformance/types/contextualTypes/jsxAttributes/contextuallyTypedStringLiteralsInJsxAttributes01.tsx @@ -2,9 +2,12 @@ // @declaration: true namespace JSX { - interface IntrinsicElements { + export interface IntrinsicElements { span: {}; } + export interface Element { + something?: any; + } } const FooComponent = (props: { foo: "A" | "B" | "C" }) => {props.foo};