Skip to content

Commit e9cd3ad

Browse files
author
Yui T
committed
Change how we look up children attribute from react.d.ts
1 parent c13383a commit e9cd3ad

File tree

2 files changed

+42
-69
lines changed

2 files changed

+42
-69
lines changed

src/compiler/checker.ts

Lines changed: 39 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -423,17 +423,20 @@ namespace ts {
423423

424424
let _jsxNamespace: string;
425425
let _jsxFactoryEntity: EntityName;
426-
let _jsxElementAttribPropInterfaceSymbol: Symbol; // JSX.ElementAttributesProperty [symbol]
427426
let _jsxElementPropertiesName: string;
427+
let _hasComputedJsxElementPropertiesName = false;
428428
let _jsxElementChildrenPropertyName: string;
429+
let _hasComputedJsxElementChildrenPropertyName = false;
429430

430431
/** Things we lazy load from the JSX namespace */
431432
const jsxTypes = createMap<Type>();
433+
432434
const JsxNames = {
433435
JSX: "JSX",
434436
IntrinsicElements: "IntrinsicElements",
435437
ElementClass: "ElementClass",
436438
ElementAttributesPropertyNameContainer: "ElementAttributesProperty",
439+
ElementChildrenAttributeNameContainer: "ElementChildrenAttribute",
437440
Element: "Element",
438441
IntrinsicAttributes: "IntrinsicAttributes",
439442
IntrinsicClassAttributes: "IntrinsicClassAttributes"
@@ -12696,7 +12699,7 @@ namespace ts {
1269612699
else if (node.parent.kind === SyntaxKind.JsxElement) {
1269712700
// JSX expression is in children of JSX Element, we will look for an "children" atttribute (we get the name from JSX.ElementAttributesProperty)
1269812701
const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
12699-
return jsxChildrenPropertyName ? getTypeOfPropertyOfType(attributesType, jsxChildrenPropertyName) : anyType;
12702+
return jsxChildrenPropertyName && jsxChildrenPropertyName !== "" ? getTypeOfPropertyOfType(attributesType, jsxChildrenPropertyName) : anyType;
1270012703
}
1270112704
else {
1270212705
// JSX expression is in JSX spread attribute
@@ -13361,7 +13364,7 @@ namespace ts {
1336113364
// Error if there is a attribute named "children" and children element.
1336213365
// This is because children element will overwrite the value from attributes
1336313366
const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
13364-
if (jsxChildrenPropertyName) {
13367+
if (jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
1336513368
if (attributesTable.has(jsxChildrenPropertyName)) {
1336613369
error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName);
1336713370
}
@@ -13474,14 +13477,34 @@ namespace ts {
1347413477
return getUnionType(map(signatures, getReturnTypeOfSignature), /*subtypeReduction*/ true);
1347513478
}
1347613479

13477-
function getPropertiesFromJsxElementAttributesProperty() {
13478-
if (!_jsxElementAttribPropInterfaceSymbol) {
13479-
// JSX
13480-
const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined);
13481-
// JSX.ElementAttributesProperty [symbol]
13482-
_jsxElementAttribPropInterfaceSymbol = jsxNamespace && getSymbol(jsxNamespace.exports, JsxNames.ElementAttributesPropertyNameContainer, SymbolFlags.Type);
13480+
/**
13481+
*
13482+
*/
13483+
function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: string): string {
13484+
// JSX
13485+
const jsxNamespace = getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined);
13486+
// JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol]
13487+
const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports, nameOfAttribPropContainer, SymbolFlags.Type);
13488+
// JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type]
13489+
const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym);
13490+
// The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute
13491+
const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType);
13492+
if (propertiesOfJsxElementAttribPropInterface) {
13493+
// Element Attributes has zero properties, so the element attributes type will be the class instance type
13494+
if (propertiesOfJsxElementAttribPropInterface.length === 0) {
13495+
return "";
13496+
}
13497+
// Element Attributes has one property, so the element attributes type will be the type of the corresponding
13498+
// property of the class instance type
13499+
else if (propertiesOfJsxElementAttribPropInterface.length === 1) {
13500+
return propertiesOfJsxElementAttribPropInterface[0].name;
13501+
}
13502+
else if (propertiesOfJsxElementAttribPropInterface.length > 1) {
13503+
// More than one property on ElementAttributesProperty is an error
13504+
error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, nameOfAttribPropContainer);
13505+
}
1348313506
}
13484-
return _jsxElementAttribPropInterfaceSymbol;
13507+
return undefined;
1348513508
}
1348613509

1348713510
/// e.g. "props" for React.d.ts,
@@ -13490,66 +13513,18 @@ namespace ts {
1349013513
/// or '' if it has 0 properties (which means every
1349113514
/// non-intrinsic elements' attributes type is the element instance type)
1349213515
function getJsxElementPropertiesName() {
13493-
if (!_jsxElementPropertiesName) {
13494-
const jsxElementAttribPropInterfaceSym = getPropertiesFromJsxElementAttributesProperty();
13495-
// JSX.ElementAttributesProperty [type]
13496-
const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym);
13497-
// The properties of JSX.ElementAttributesProperty
13498-
const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType);
13499-
13500-
// if there is a property in JSX.ElementAttributesProperty
13501-
// i.e.
13502-
// interface ElementAttributesProperty {
13503-
// props: {
13504-
// children?: any;
13505-
// };
13506-
// }
13507-
if (propertiesOfJsxElementAttribPropInterface) {
13508-
// Element Attributes has zero properties, so the element attributes type will be the class instance type
13509-
if (propertiesOfJsxElementAttribPropInterface.length === 0) {
13510-
_jsxElementPropertiesName = "";
13511-
}
13512-
// Element Attributes has one property, so the element attributes type will be the type of the corresponding
13513-
// property of the class instance type
13514-
else if (propertiesOfJsxElementAttribPropInterface.length === 1) {
13515-
_jsxElementPropertiesName = propertiesOfJsxElementAttribPropInterface[0].name;
13516-
}
13517-
// More than one property on ElementAttributesProperty is an error
13518-
else {
13519-
error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, JsxNames.ElementAttributesPropertyNameContainer);
13520-
_jsxElementPropertiesName = undefined;
13521-
}
13522-
}
13523-
else {
13524-
// No interface exists, so the element attributes type will be an implicit any
13525-
_jsxElementPropertiesName = undefined;
13526-
}
13516+
if (!_hasComputedJsxElementPropertiesName) {
13517+
_hasComputedJsxElementPropertiesName = true;
13518+
_jsxElementPropertiesName = getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer);
1352713519
}
1352813520

1352913521
return _jsxElementPropertiesName;
1353013522
}
1353113523

1353213524
function getJsxElementChildrenPropertyname(): string {
13533-
if (!_jsxElementChildrenPropertyName) {
13534-
const jsxElementAttribPropInterfaceSym = getPropertiesFromJsxElementAttributesProperty();
13535-
// JSX.ElementAttributesProperty [type]
13536-
const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym);
13537-
// The properties of JSX.ElementAttributesProperty
13538-
const propertiesOfJsxElementAttribPropInterface = jsxElementAttribPropInterfaceType && getPropertiesOfType(jsxElementAttribPropInterfaceType);
13539-
// if there is a property in JSX.ElementAttributesProperty
13540-
// i.e.
13541-
// interface ElementAttributesProperty {
13542-
// props: {
13543-
// children?: any;
13544-
// };
13545-
// }
13546-
if (propertiesOfJsxElementAttribPropInterface && propertiesOfJsxElementAttribPropInterface.length === 1) {
13547-
const propsType = getTypeOfSymbol(propertiesOfJsxElementAttribPropInterface[0]);
13548-
const propertiesOfProps = propsType && getPropertiesOfType(propsType);
13549-
if (propertiesOfProps && propertiesOfProps.length === 1) {
13550-
_jsxElementChildrenPropertyName = propertiesOfProps[0].name;
13551-
}
13552-
}
13525+
if (!_hasComputedJsxElementChildrenPropertyName) {
13526+
_hasComputedJsxElementChildrenPropertyName = true;
13527+
_jsxElementChildrenPropertyName = getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer);
1355313528
}
1355413529

1355513530
return _jsxElementChildrenPropertyName;

tests/lib/react.d.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,11 +2359,9 @@ declare namespace JSX {
23592359
interface ElementClass extends React.Component<any, any> {
23602360
render(): JSX.Element | null;
23612361
}
2362-
interface ElementAttributesProperty {
2363-
props: {
2364-
children: any;
2365-
};
2366-
}
2362+
interface ElementAttributesProperty { props; }
2363+
2364+
interface ElementChildrenAttribute { children; }
23672365

23682366
interface IntrinsicAttributes extends React.Attributes { }
23692367

0 commit comments

Comments
 (0)