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

Commit 95215cd

Browse files
unstubbableKnisterPeter
authored andcommitted
feat: export complex types as type aliases or interfaces (#272)
Union, intersection and object types are now exported as well, along with the component props interface.
1 parent 64a75ea commit 95215cd

7 files changed

+65
-17
lines changed

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@
6666
"babylon": "6.15.0",
6767
"dts-dom": "0.1.12",
6868
"get-stdin": "5.0.1",
69-
"meow": "3.7.0"
69+
"meow": "3.7.0",
70+
"pascal-case": "2.0.0"
7071
},
7172
"config": {
7273
"commitizen": {

Diff for: src/typings.ts

+37
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as ASTQ from 'astq';
22
import * as dom from 'dts-dom';
3+
import pascalCase = require('pascal-case');
34
import { InstanceOfResolver } from './index';
45
import * as types from './types';
56

@@ -69,7 +70,9 @@ function createExportedTypes(m: dom.ModuleDeclaration, ast: AstQuery, componentN
6970
interf.flags = dom.DeclarationFlags.Export;
7071
if (propTypes) {
7172
createPropTypeTypings(interf, ast, propTypes, propTypesName);
73+
extractComplexTypes(m, interf, componentName);
7274
}
75+
7376
if (propTypes || classComponent) {
7477
m.members.push(interf);
7578
}
@@ -116,6 +119,40 @@ function createPropTypeTypings(interf: dom.InterfaceDeclaration, ast: AstQuery,
116119
});
117120
}
118121

122+
function extractComplexTypes(m: dom.ModuleDeclaration, interf: dom.InterfaceDeclaration,
123+
componentName: string): void {
124+
interf.members.forEach((member) => {
125+
if (member.kind === 'property' && isExtractableType(member.type)) {
126+
const name = `${componentName}${pascalCase(member.name)}`;
127+
const extractedMember = createModuleMember(name, member.type);
128+
extractedMember.flags = dom.DeclarationFlags.Export;
129+
m.members.push(extractedMember);
130+
member.type = dom.create.namedTypeReference(name);
131+
}
132+
});
133+
}
134+
135+
type ExtractableType = dom.UnionType | dom.IntersectionType | dom.ObjectType;
136+
137+
function isExtractableType(type: dom.Type): type is ExtractableType {
138+
if (typeof type === 'object') {
139+
return ['union', 'intersection', 'object'].indexOf(type.kind) > -1;
140+
}
141+
return false;
142+
}
143+
144+
function createModuleMember(name: string, type: ExtractableType): dom.ModuleMember {
145+
switch (type.kind) {
146+
case 'intersection':
147+
case 'union':
148+
return dom.create.alias(name, type);
149+
case 'object':
150+
const interf = dom.create.interface(name);
151+
interf.members = type.members;
152+
return interf;
153+
}
154+
}
155+
119156
function getUniqueNames(input: string[]): string[] {
120157
return Object.keys(input.reduce((all: any, name: string) => {
121158
all[name] = true;

Diff for: tests/es6-class.d.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
declare module 'component' {
22
import * as React from 'react';
33
import Message from './path/to/Message';
4+
export type ComponentOptionalEnum = 'News' | 'Photos' | 1 | 2;
5+
export type ComponentOptionalUnion = string | number;
6+
export interface ComponentOptionalObjectWithShape {
7+
color?: string;
8+
fontSize?: number;
9+
}
10+
export type ComponentRequiredUnion = any[] | boolean;
411
export interface ComponentProps {
512
/**
613
* This is a jsdoc comment for optionalAny.
@@ -15,16 +22,13 @@ declare module 'component' {
1522
optionalNode?: React.ReactNode;
1623
optionalElement?: React.ReactElement<any>;
1724
optionalMessage?: typeof Message;
18-
optionalEnum?: 'News' | 'Photos' | 1 | 2;
19-
optionalUnion?: string | number;
25+
optionalEnum?: ComponentOptionalEnum;
26+
optionalUnion?: ComponentOptionalUnion;
2027
optionalArrayOf?: number[];
21-
optionalObjectWithShape?: {
22-
color?: string;
23-
fontSize?: number;
24-
};
28+
optionalObjectWithShape?: ComponentOptionalObjectWithShape;
2529
requiredFunc: (...args: any[])=>any;
2630
requiredAny: any;
27-
requiredUnion: any[] | boolean;
31+
requiredUnion: ComponentRequiredUnion;
2832
requiredArrayOf: string[];
2933
requiredArrayOfObjectsWithShape: {
3034
color?: string;

Diff for: tests/es7-class-top-level-module.d.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import * as React from 'react';
22
import Message from './path/to/Message';
3+
export type ComponentOptionalUnion = string | number;
4+
export type ComponentRequiredUnion = any[] | boolean;
35
export interface ComponentProps {
46
/**
57
* This is a jsdoc comment for optionalAny.
@@ -14,11 +16,11 @@ export interface ComponentProps {
1416
optionalNode?: React.ReactNode;
1517
optionalElement?: React.ReactElement<any>;
1618
optionalMessage?: typeof Message;
17-
optionalUnion?: string | number;
19+
optionalUnion?: ComponentOptionalUnion;
1820
optionalArrayOf?: number[];
1921
requiredFunc: (...args: any[])=>any;
2022
requiredAny: any;
21-
requiredUnion: any[] | boolean;
23+
requiredUnion: ComponentRequiredUnion;
2224
requiredArrayOf: string[];
2325
}
2426
export default class Component extends React.Component<ComponentProps, any>{

Diff for: tests/es7-class.d.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
declare module 'component' {
22
import * as React from 'react';
33
import Message from './path/to/Message';
4+
export type ComponentOptionalUnion = string | number;
5+
export type ComponentRequiredUnion = any[] | boolean;
46
export interface ComponentProps {
57
/**
68
* This is a jsdoc comment for optionalAny.
@@ -15,11 +17,11 @@ declare module 'component' {
1517
optionalNode?: React.ReactNode;
1618
optionalElement?: React.ReactElement<any>;
1719
optionalMessage?: typeof Message;
18-
optionalUnion?: string | number;
20+
optionalUnion?: ComponentOptionalUnion;
1921
optionalArrayOf?: number[];
2022
requiredFunc: (...args: any[])=>any;
2123
requiredAny: any;
22-
requiredUnion: any[] | boolean;
24+
requiredUnion: ComponentRequiredUnion;
2325
requiredArrayOf: string[];
2426
}
2527
export default class Component extends React.Component<ComponentProps, any>{

Diff for: tests/references-in-proptypes.d.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
declare module 'component' {
22
import * as React from 'react';
3+
export type SomeComponentSomeOneOf = 'foo' | 'bar';
4+
export interface SomeComponentSomeShape {
5+
string?: string;
6+
}
37
export interface SomeComponentProps {
4-
someEnum?: 'foo' | 'bar';
5-
someShape?: {
6-
string?: string;
7-
};
8+
someOneOf?: SomeComponentSomeOneOf;
9+
someShape?: SomeComponentSomeShape;
810
}
911
export default class SomeComponent extends React.Component<SomeComponentProps, any>{
1012
}

Diff for: tests/references-in-proptypes.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const shape = { string: React.PropTypes.string };
55

66
export default class SomeComponent extends React.Component {
77
static propTypes = {
8-
someEnum: React.PropTypes.oneOf(fooOrBar),
8+
someOneOf: React.PropTypes.oneOf(fooOrBar),
99
someShape: React.PropTypes.shape(shape)
1010
};
1111
}

0 commit comments

Comments
 (0)