diff --git a/src/typings.ts b/src/typings.ts index 503ba9bd..4312ab12 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -48,7 +48,7 @@ export function createTypings(moduleName: string|null, programAst: any, options: const m = dom.create.module(moduleName || 'moduleName'); if (hasReactClass(ast, reactComponentName)) { - m.members.push(dom.create.importNamed('Component', reactImport)); + m.members.push(dom.create.importNamed(reactComponentName || 'Component', reactImport)); } else { tripleSlashDirectives.push(dom.create.tripleSlashReferenceTypesDirective('react')); } @@ -95,19 +95,29 @@ function createExportedTypes(m: dom.ModuleDeclaration, ast: AstQuery, componentN } if (classComponent) { - const classDecl = dom.create.class(componentName); - classDecl.baseType = dom.create.interface(`Component<${interf.name}, any>`); - classDecl.flags = exportType; - classDecl.members.push(dom.create.method('render', [], dom.create.namedTypeReference('JSX.Element'))); - m.members.push(classDecl); + createExportedClassComponent(m, componentName, reactComponentName, exportType, interf); } else { - const funcDelc = dom.create.function(componentName, propTypes ? [dom.create.parameter('props', interf)] : [], - dom.create.namedTypeReference('JSX.Element')); - funcDelc.flags = exportType; - m.members.push(funcDelc); + createExportedFunctionalComponent(m, componentName, propTypes, exportType, interf); } } +function createExportedClassComponent(m: dom.ModuleDeclaration, componentName: string, + reactComponentName: string|undefined, exportType: dom.DeclarationFlags, interf: dom.InterfaceDeclaration): void { + const classDecl = dom.create.class(componentName); + classDecl.baseType = dom.create.interface(`${reactComponentName || 'Component'}<${interf.name}, any>`); + classDecl.flags = exportType; + classDecl.members.push(dom.create.method('render', [], dom.create.namedTypeReference('JSX.Element'))); + m.members.push(classDecl); +} + +function createExportedFunctionalComponent(m: dom.ModuleDeclaration, componentName: string, propTypes: any, + exportType: dom.DeclarationFlags, interf: dom.InterfaceDeclaration): void { + const funcDelc = dom.create.function(componentName, propTypes ? [dom.create.parameter('props', interf)] : [], + dom.create.namedTypeReference('JSX.Element')); + funcDelc.flags = exportType; + m.members.push(funcDelc); +} + function createPropTypeTypings(interf: dom.InterfaceDeclaration, ast: AstQuery, propTypes: any, importedPropTypes: ImportedPropTypes, options: IOptions): void { const res = ast.querySubtree(propTypes, ` @@ -209,7 +219,7 @@ function getReactComponentName(ast: AstQuery): string|undefined { /:source StringLiteral[@value == 'react'] ] /:specifiers *[ - / Identifier[@name == 'Component'] + / Identifier[@name == 'Component'] || / Identifier[@name == 'PureComponent'] ] /:local Identifier `); diff --git a/tests/parsing-test.ts b/tests/parsing-test.ts index 198ecab0..b3d37ebf 100644 --- a/tests/parsing-test.ts +++ b/tests/parsing-test.ts @@ -111,3 +111,6 @@ test('Parsing should suppport props-types repo (with a default import)', t => { test('Parsing should support an SFC with default export babeled to es6', t => { compare(t, 'component', 'stateless-export-as-default.js', 'stateless-export-as-default.d.ts'); }); +test('Parsing should suppport components that extend PureComponent', t => { + compare(t, 'component', 'pure-component.jsx', 'pure-component.d.ts'); +}); diff --git a/tests/pure-component.d.ts b/tests/pure-component.d.ts new file mode 100644 index 00000000..eb7b813f --- /dev/null +++ b/tests/pure-component.d.ts @@ -0,0 +1,11 @@ +declare module 'component' { + import {PureComponent} from 'react'; + + export interface Props { + optionalString?: string; + } + + export default class extends PureComponent { + render(): JSX.Element; + } +} diff --git a/tests/pure-component.jsx b/tests/pure-component.jsx new file mode 100644 index 00000000..73ae50ed --- /dev/null +++ b/tests/pure-component.jsx @@ -0,0 +1,15 @@ +import {PureComponent} from 'react'; +import * as PropTypes from 'prop-types'; + +export default class extends PureComponent { + + static propTypes = { + optionalString: PropTypes.string + }; + + render() { + return ( +
+ ); + } +}