Skip to content

Commit 096c15b

Browse files
author
Kanchalai Tanglertsampan
committed
Defer get JSX.Element type
allow null to be returned in SFC
1 parent ef25b25 commit 096c15b

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

src/compiler/checker.ts

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ namespace ts {
278278
let deferredGlobalAsyncIterableIteratorType: GenericType;
279279
let deferredGlobalTemplateStringsArrayType: ObjectType;
280280
let deferredJsxElementClassType: Type;
281+
let deferredJsxElementType: Type;
282+
let deferredJsxStatelessElementType: Type;
281283

282284
let deferredNodes: Node[];
283285
let deferredUnusedIdentifierNodes: Node[];
@@ -398,7 +400,6 @@ namespace ts {
398400
});
399401
const typeofType = createTypeofType();
400402

401-
let jsxElementType: Type;
402403
let _jsxNamespace: string;
403404
let _jsxFactoryEntity: EntityName;
404405

@@ -12306,12 +12307,12 @@ namespace ts {
1230612307
type.flags & TypeFlags.UnionOrIntersection && !forEach((<UnionOrIntersectionType>type).types, t => !isValidSpreadType(t)));
1230712308
}
1230812309

12309-
function checkJsxSelfClosingElement(node: JsxSelfClosingElement) {
12310+
function checkJsxSelfClosingElement(node: JsxSelfClosingElement): Type {
1231012311
checkJsxOpeningLikeElement(node);
12311-
return jsxElementType || anyType;
12312+
return getJsxGlobalElementType() || anyType;
1231212313
}
1231312314

12314-
function checkJsxElement(node: JsxElement) {
12315+
function checkJsxElement(node: JsxElement): Type {
1231512316
// Check attributes
1231612317
checkJsxOpeningLikeElement(node.openingElement);
1231712318

@@ -12338,7 +12339,7 @@ namespace ts {
1233812339
}
1233912340
}
1234012341

12341-
return jsxElementType || anyType;
12342+
return getJsxGlobalElementType() || anyType;
1234212343
}
1234312344

1234412345
/**
@@ -12579,13 +12580,14 @@ namespace ts {
1257912580
function defaultTryGetJsxStatelessFunctionAttributesType(openingLikeElement: JsxOpeningLikeElement, elementType: Type, elemInstanceType: Type, elementClassType?: Type): Type {
1258012581
Debug.assert(!(elementType.flags & TypeFlags.Union));
1258112582
if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) {
12582-
if (jsxElementType) {
12583+
const jsxStatelessElementType = getJsxGlobalStatelessElementType();
12584+
if (jsxStatelessElementType) {
1258312585
// We don't call getResolvedSignature here because we have already resolve the type of JSX Element.
1258412586
const callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined);
1258512587
if (callSignature !== unknownSignature) {
1258612588
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
1258712589
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
12588-
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
12590+
if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) {
1258912591
// Intersect in JSX.IntrinsicAttributes if it exists
1259012592
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
1259112593
if (intrinsicAttributes !== unknownType) {
@@ -12613,7 +12615,8 @@ namespace ts {
1261312615
Debug.assert(!(elementType.flags & TypeFlags.Union));
1261412616
if (!elementClassType || !isTypeAssignableTo(elemInstanceType, elementClassType)) {
1261512617
// Is this is a stateless function component? See if its single signature's return type is assignable to the JSX Element Type
12616-
if (jsxElementType) {
12618+
const jsxStatelessElementType = getJsxGlobalStatelessElementType();
12619+
if (jsxStatelessElementType) {
1261712620
// We don't call getResolvedSignature because here we have already resolve the type of JSX Element.
1261812621
const candidatesOutArray: Signature[] = [];
1261912622
getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, candidatesOutArray);
@@ -12622,7 +12625,7 @@ namespace ts {
1262212625
for (const candidate of candidatesOutArray) {
1262312626
const callReturnType = getReturnTypeOfSignature(candidate);
1262412627
const paramType = callReturnType && (candidate.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(candidate.parameters[0]));
12625-
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
12628+
if (callReturnType && isTypeAssignableTo(callReturnType, jsxStatelessElementType)) {
1262612629
let shouldBeCandidate = true;
1262712630
for (const attribute of openingLikeElement.attributes.properties) {
1262812631
if (isJsxAttribute(attribute) &&
@@ -12871,6 +12874,23 @@ namespace ts {
1287112874
return deferredJsxElementClassType;
1287212875
}
1287312876

12877+
function getJsxGlobalElementType(): Type {
12878+
if (!deferredJsxElementType) {
12879+
deferredJsxElementType = getExportedTypeFromNamespace(JsxNames.JSX, JsxNames.Element);
12880+
}
12881+
return deferredJsxElementType;
12882+
}
12883+
12884+
function getJsxGlobalStatelessElementType(): Type {
12885+
if (!deferredJsxStatelessElementType) {
12886+
const jsxElementType = getJsxGlobalElementType();
12887+
if (jsxElementType){
12888+
deferredJsxStatelessElementType = getUnionType([jsxElementType, nullType]);
12889+
}
12890+
}
12891+
return deferredJsxStatelessElementType;
12892+
}
12893+
1287412894
/**
1287512895
* Returns all the properties of the Jsx.IntrinsicElements interface
1287612896
*/
@@ -12885,7 +12905,7 @@ namespace ts {
1288512905
error(errorNode, Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided);
1288612906
}
1288712907

12888-
if (jsxElementType === undefined) {
12908+
if (getJsxGlobalElementType() === undefined) {
1288912909
if (compilerOptions.noImplicitAny) {
1289012910
error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist);
1289112911
}
@@ -21917,7 +21937,6 @@ namespace ts {
2191721937
globalNumberType = getGlobalType("Number", /*arity*/ 0, /*reportErrors*/ true);
2191821938
globalBooleanType = getGlobalType("Boolean", /*arity*/ 0, /*reportErrors*/ true);
2191921939
globalRegExpType = getGlobalType("RegExp", /*arity*/ 0, /*reportErrors*/ true);
21920-
jsxElementType = getExportedTypeFromNamespace("JSX", JsxNames.Element);
2192121940
anyArrayType = createArrayType(anyType);
2192221941
autoArrayType = createArrayType(autoType);
2192321942

0 commit comments

Comments
 (0)