Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
feat: support generating types for PureComponents
Browse files Browse the repository at this point in the history
  • Loading branch information
unstubbable committed Feb 7, 2018
1 parent 8210a62 commit 7343af1
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 11 deletions.
32 changes: 21 additions & 11 deletions src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
}
Expand Down Expand Up @@ -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, `
Expand Down Expand Up @@ -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
`);
Expand Down
3 changes: 3 additions & 0 deletions tests/parsing-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
11 changes: 11 additions & 0 deletions tests/pure-component.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
declare module 'component' {
import {PureComponent} from 'react';

export interface Props {
optionalString?: string;
}

export default class extends PureComponent<Props, any> {
render(): JSX.Element;
}
}
15 changes: 15 additions & 0 deletions tests/pure-component.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<div></div>
);
}
}

0 comments on commit 7343af1

Please sign in to comment.