Defer get JSX.Element type

allow null to be returned in SFC
This commit is contained in:
Kanchalai Tanglertsampan
2017-02-17 12:58:17 -08:00
parent ef25b25c1f
commit 096c15b0de

View File

@@ -278,6 +278,8 @@ namespace ts {
let deferredGlobalAsyncIterableIteratorType: GenericType;
let deferredGlobalTemplateStringsArrayType: ObjectType;
let deferredJsxElementClassType: Type;
let deferredJsxElementType: Type;
let deferredJsxStatelessElementType: Type;
let deferredNodes: Node[];
let deferredUnusedIdentifierNodes: Node[];
@@ -398,7 +400,6 @@ namespace ts {
});
const typeofType = createTypeofType();
let jsxElementType: Type;
let _jsxNamespace: string;
let _jsxFactoryEntity: EntityName;
@@ -12306,12 +12307,12 @@ namespace ts {
type.flags & TypeFlags.UnionOrIntersection && !forEach((<UnionOrIntersectionType>type).types, t => !isValidSpreadType(t)));
}
function checkJsxSelfClosingElement(node: JsxSelfClosingElement) {
function checkJsxSelfClosingElement(node: JsxSelfClosingElement): Type {
checkJsxOpeningLikeElement(node);
return jsxElementType || anyType;
return getJsxGlobalElementType() || anyType;
}
function checkJsxElement(node: JsxElement) {
function checkJsxElement(node: JsxElement): Type {
// Check attributes
checkJsxOpeningLikeElement(node.openingElement);
@@ -12338,7 +12339,7 @@ namespace ts {
}
}
return jsxElementType || anyType;
return getJsxGlobalElementType() || anyType;
}
/**
@@ -12579,13 +12580,14 @@ namespace ts {
function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type {
Debug.assert(!(elementType.flags & TypeFlags.Union));
if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) {
if (jsxElementType) {
const jsxStatelessElementType = getJsxGlobalStatelessElementType();
if (jsxStatelessElementType) {
// We don't call getResolvedSignature here because we have already resolve the type of JSX Element.
const callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined);
if (callSignature !== unknownSignature) {
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) {
// Intersect in JSX.IntrinsicAttributes if it exists
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
if (intrinsicAttributes !== unknownType) {
@@ -12613,7 +12615,8 @@ namespace ts {
Debug.assert(!(elementType.flags & TypeFlags.Union));
if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) {
// Is this is a stateless function component? See if its single signature's return type is assignable to the JSX Element Type
if (jsxElementType) {
const jsxStatelessElementType = getJsxGlobalStatelessElementType();
if (jsxStatelessElementType) {
// We don't call getResolvedSignature because here we have already resolve the type of JSX Element.
const candidatesOutArray: Signature[] = [];
getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray);
@@ -12622,7 +12625,7 @@ namespace ts {
for (const candidate of candidatesOutArray) {
const callReturnType = getReturnTypeOfSignature(candidate);
const paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0]));
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) {
let shouldBeCandidate = true;
for (const attribute of openingLikeElement.attributes.properties) {
if (isJsxAttribute(attribute) &&
@@ -12871,6 +12874,23 @@ namespace ts {
return deferredJsxElementClassType;
}
function getJsxGlobalElementType(): Type {
if (!deferredJsxElementType) {
deferredJsxElementType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.Element);
}
return deferredJsxElementType;
}
function getJsxGlobalStatelessElementType(): Type {
if (!deferredJsxStatelessElementType) {
const jsxElementType = getJsxGlobalElementType();
if (jsxElementType){
deferredJsxStatelessElementType = getUnionType([jsxElementType, nullType]);
}
}
return deferredJsxStatelessElementType;
}
/**
* Returns all the properties of the Jsx.IntrinsicElements interface
*/
@@ -12885,7 +12905,7 @@ namespace ts {
error(errorNode, Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided);
}
if (jsxElementType === undefined) {
if (getJsxGlobalElementType() === undefined) {
if (compilerOptions.noImplicitAny) {
error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist);
}
@@ -21917,7 +21937,6 @@ namespace ts {
globalNumberType = getGlobalType("Number", /*arity*/ 0, /*reportErrors*/ true);
globalBooleanType = getGlobalType("Boolean", /*arity*/ 0, /*reportErrors*/ true);
globalRegExpType = getGlobalType("RegExp", /*arity*/ 0, /*reportErrors*/ true);
jsxElementType = getExportedTypeFromNamespace("JSX", JsxNames.Element);
anyArrayType = createArrayType(anyType);
autoArrayType = createArrayType(autoType);