Merge pull request #7308 from RyanCavanaugh/fix7286

Don't crash if there's no JSX.Element during SFC resolution
This commit is contained in:
Ryan Cavanaugh
2016-03-01 10:12:17 -08:00
8 changed files with 67 additions and 17 deletions
+13 -11
View File
@@ -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;
}
}
@@ -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" }) => <span>{props.foo}</span>;
@@ -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" }) => <span>{props.foo}</span>;
@@ -24,7 +27,13 @@ var FooComponent = function (props) { return <span>{props.foo}</span>; };
//// [contextuallyTypedStringLiteralsInJsxAttributes01.d.ts]
declare namespace JSX {
interface IntrinsicElements {
span: {};
}
interface Element {
something?: any;
}
}
declare const FooComponent: (props: {
foo: "A" | "B" | "C";
}) => any;
}) => JSX.Element;
@@ -0,0 +1,9 @@
//// [test.tsx]
function Test() { }
<Test></Test>
//// [test.jsx]
function Test() { }
<Test></Test>;
@@ -0,0 +1,9 @@
=== tests/cases/conformance/jsx/test.tsx ===
function Test() { }
>Test : Symbol(Test, Decl(test.tsx, 0, 0))
<Test></Test>
>Test : Symbol(Test, Decl(test.tsx, 0, 0))
>Test : Symbol(Test, Decl(test.tsx, 0, 0))
@@ -0,0 +1,10 @@
=== tests/cases/conformance/jsx/test.tsx ===
function Test() { }
>Test : () => void
<Test></Test>
><Test></Test> : any
>Test : any
>Test : any
@@ -0,0 +1,5 @@
//@jsx: preserve
//@filename: test.tsx
function Test() { }
<Test></Test>
@@ -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" }) => <span>{props.foo}</span>;