From f7d2a3d545a59b3c7312f43cc424c1004a67371f Mon Sep 17 00:00:00 2001 From: Julian Schuster Date: Thu, 2 Dec 2021 18:00:59 -0300 Subject: [PATCH] changed class component typing generation with funcional component generation --- src/index.ts | 53 +++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/index.ts b/src/index.ts index 3165f04..c876445 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,22 +26,25 @@ export interface Options { export function generate(options: Options, findAll?: boolean): string { let result: string = ''; - let baseType: string = 'React.Component'; + let baseType: string = 'React.FC'; - const { input, output, isBaseClass, propTypesComposition, imports } = options; + const {input, output, isBaseClass, propTypesComposition, imports} = options; + + const componentName = input.substring(input.lastIndexOf('/') + 1, input.lastIndexOf('.')); const content: string = fs.readFileSync(input, 'utf8'); - const [componentInfo, ...childs] = parse(content, findAll ? resolver.findAllComponentDefinitions : undefined); + const [componentInfo, ...childs] = (parse(content, findAll ? resolver.findAllComponentDefinitions : undefined)).sort((a) => (a.displayName === componentName ? -1 : 1));; const className = isBaseClass ? Utils.writeGeneric(componentInfo.displayName, 'T = any') : componentInfo.displayName; const importDefinitions: dom.Import[] = []; const interfaceDefinitions: dom.InterfaceDeclaration[] = []; + const intersectDefinitions: dom.PropertyDeclaration[] = []; if (componentInfo) { - const propsIntefaceName = `${componentInfo.displayName}Props`; - const propsDefinition = dom.create.interface(propsIntefaceName, dom.DeclarationFlags.Export); + const propsInterfaceName = `${componentInfo.displayName}Props`; + const propsDefinition = dom.create.interface(propsInterfaceName, dom.DeclarationFlags.Export); const importDefinition = dom.create.importAll('React', 'react'); - const classDefinition = dom.create.class(className, dom.DeclarationFlags.ExportDefault); + const constDefinition = dom.create.const(className, Utils.writeGeneric('React.FC', propsInterfaceName), dom.DeclarationFlags.None); importDefinitions.push(importDefinition); @@ -57,14 +60,14 @@ export function generate(options: Options, findAll?: boolean): string { if (keys.length > 0) { keys.forEach(key => { - const prop = { ...props[key], name: key }; + const prop = {...props[key], name: key}; if (!prop.type) { return; } const propResult = Utils.generateProp(prop); if (propResult) { - const { property, interfaces } = propResult; + const {property, interfaces} = propResult; propsDefinition.members.push(property); if (interfaces && interfaces.length > 0) { interfaceDefinitions.push(...interfaces); @@ -73,14 +76,14 @@ export function generate(options: Options, findAll?: boolean): string { }); } - baseType = Utils.writeGeneric('React.Component', isBaseClass ? 'T' : propsIntefaceName); + baseType = Utils.writeGeneric('React.FC', isBaseClass ? 'T' : propsInterfaceName); interfaceDefinitions.push(propsDefinition); } if (childs && childs.length > 0) { - childs.forEach(({displayName, props}) => { + childs.map(({displayName, props}) => { const propsIntefaceName2 = `${displayName}Props`; - const propsDefinition2 = dom.create.interface(propsIntefaceName2, dom.DeclarationFlags.Export); + const propsDefinition2 = dom.create.interface(propsIntefaceName2, dom.DeclarationFlags.None); const importDefinition2 = dom.create.importAll('React', 'react'); importDefinitions.push(importDefinition2); if (imports && imports.length > 0) { @@ -108,9 +111,11 @@ export function generate(options: Options, findAll?: boolean): string { } // baseType = Utils.writeGeneric('React.Component', isBaseClass ? 'T' : propsIntefaceName); interfaceDefinitions.push(propsDefinition2); - classDefinition.members.push(dom.create.property(displayName, Utils.writeGeneric('React.Component', propsIntefaceName2))); + intersectDefinitions.push(dom.create.property(displayName, Utils.writeGeneric('React.FC', propsIntefaceName2))); + } - }) + }); + } if (propTypesComposition && propTypesComposition.length > 0) { @@ -123,17 +128,17 @@ export function generate(options: Options, findAll?: boolean): string { if (options.extends) { if (options.extends.import) { - const { from, named } = options.extends.import; + const {from, named} = options.extends.import; importDefinitions.push(Utils.createImport(from, options.extends.import.default, named)); const baseTypeName = named as string || options.extends.import.default as string; - const genericName = isBaseClass ? 'T' : propsIntefaceName; + const genericName = isBaseClass ? 'T' : propsInterfaceName; baseType = Utils.writeGeneric(baseTypeName, genericName); } } - if (componentInfo.methods) { + /*if (componentInfo.methods) { componentInfo.methods.forEach(method => { - const { params, returns } = method; + const {params, returns} = method; const parameters: dom.Parameter[] = []; if (params && params.length > 0) { params.forEach(param => { @@ -142,19 +147,21 @@ export function generate(options: Options, findAll?: boolean): string { }); } const returnType = returns ? returns.type.name : 'any'; - classDefinition.members.push(dom.create.method(method.name, parameters, Utils.getType(returnType))); + constDefinition.members.push(dom.create.method(method.name, parameters, Utils.getType(returnType))); }); - } + }*/ result += dom.emit(dom.create.imports(importDefinitions)); interfaceDefinitions.forEach(x => result += dom.emit(x)); - classDefinition.baseType = baseType; - result += dom.emit(classDefinition); + constDefinition.type = dom.create.intersection([baseType, dom.create.objectType(intersectDefinitions)]); + result += dom.emit(constDefinition); + result += ` +export default ${componentInfo.displayName}`; if (result) { const fileName = output || input.split('.')[0] + '.d.ts'; - result = prettier.format(result, { parser: 'typescript' }); - fs.writeFileSync(fileName, result, { flag: 'w', encoding: 'utf8' }); + result = prettier.format(result, {parser: 'typescript'}); + fs.writeFileSync(fileName, result, {flag: 'w', encoding: 'utf8'}); return result; } }