diff --git a/src/__tests__/data/SeparateDefaultProps.tsx b/src/__tests__/data/SeparateDefaultProps.tsx
new file mode 100644
index 00000000..34910113
--- /dev/null
+++ b/src/__tests__/data/SeparateDefaultProps.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react';
+
+const defaultProps = {
+ id: 123,
+ disabled: false
+};
+
+interface SeparateDefaultPropsProps {
+ id: number;
+ disabled: boolean;
+}
+
+/** SeparateDefaultProps description */
+export const SeparateDefaultProps = (props: SeparateDefaultPropsProps) => (
+
test
+);
+
+SeparateDefaultProps.defaultProps = defaultProps;
diff --git a/src/__tests__/data/SeparateDefaultPropsIndividual.tsx b/src/__tests__/data/SeparateDefaultPropsIndividual.tsx
new file mode 100644
index 00000000..db1031b6
--- /dev/null
+++ b/src/__tests__/data/SeparateDefaultPropsIndividual.tsx
@@ -0,0 +1,25 @@
+import * as React from 'react';
+
+const defaultProps2 = {
+ id: 123
+};
+
+const defaultProps = {
+ id: defaultProps2.id,
+ disabled: false
+};
+
+interface SeparateDefaultPropsIndividualProps {
+ id: number;
+ disabled: boolean;
+}
+
+/** SeparateDefaultPropsIndividual description */
+export const SeparateDefaultPropsIndividual = (
+ props: SeparateDefaultPropsIndividualProps
+) => test
;
+
+SeparateDefaultPropsIndividual.defaultProps = {
+ id: defaultProps.id,
+ disabled: defaultProps.disabled
+};
diff --git a/src/__tests__/parser.ts b/src/__tests__/parser.ts
index 2216f4e4..1ad72a01 100644
--- a/src/__tests__/parser.ts
+++ b/src/__tests__/parser.ts
@@ -982,6 +982,44 @@ describe('parser', () => {
});
});
+ it('should defaultProps in variable', () => {
+ check('SeparateDefaultProps', {
+ SeparateDefaultProps: {
+ disabled: {
+ description: '',
+ required: false,
+ defaultValue: false,
+ type: 'boolean'
+ },
+ id: {
+ description: '',
+ required: false,
+ defaultValue: 123,
+ type: 'number'
+ }
+ }
+ });
+ });
+
+ it('should defaultProps accessed variable', () => {
+ check('SeparateDefaultPropsIndividual', {
+ SeparateDefaultPropsIndividual: {
+ disabled: {
+ description: '',
+ required: false,
+ defaultValue: false,
+ type: 'boolean'
+ },
+ id: {
+ description: '',
+ required: false,
+ defaultValue: 123,
+ type: 'number'
+ }
+ }
+ });
+ });
+
describe('Extracting literal values from enums', () => {
it('extracts literal values from enum', () => {
check(
diff --git a/src/parser.ts b/src/parser.ts
index b732523d..d26f7d05 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -141,7 +141,9 @@ export function withCustomConfig(
if (error !== undefined) {
// tslint:disable-next-line: max-line-length
- const errorText = `Cannot load custom tsconfig.json from provided path: ${tsconfigPath}, with error code: ${error.code}, message: ${error.messageText}`;
+ const errorText = `Cannot load custom tsconfig.json from provided path: ${tsconfigPath}, with error code: ${
+ error.code
+ }, message: ${error.messageText}`;
throw new Error(errorText);
}
@@ -775,9 +777,9 @@ export class Parser {
let propMap = {};
if (properties) {
- propMap = this.getPropMap(
- properties as ts.NodeArray
- );
+ propMap = this.getPropMap(properties as ts.NodeArray<
+ ts.PropertyAssignment
+ >);
}
return {
@@ -787,13 +789,29 @@ export class Parser {
} else if (statementIsStatelessWithDefaultProps(statement)) {
let propMap = {};
(statement as ts.ExpressionStatement).getChildren().forEach(child => {
- const { right } = child as ts.BinaryExpression;
+ let { right } = child as ts.BinaryExpression;
+
+ if (right && ts.isIdentifier(right)) {
+ const value = ((source as any).locals as ts.SymbolTable).get(
+ right.escapedText
+ );
+
+ if (
+ value &&
+ value.valueDeclaration &&
+ ts.isVariableDeclaration(value.valueDeclaration) &&
+ value.valueDeclaration.initializer
+ ) {
+ right = value.valueDeclaration.initializer;
+ }
+ }
+
if (right) {
const { properties } = right as ts.ObjectLiteralExpression;
if (properties) {
- propMap = this.getPropMap(
- properties as ts.NodeArray
- );
+ propMap = this.getPropMap(properties as ts.NodeArray<
+ ts.PropertyAssignment
+ >);
}
}
});
@@ -867,7 +885,22 @@ export class Parser {
return (initializer as ts.Identifier).text === 'undefined'
? 'undefined'
: null;
- case ts.SyntaxKind.PropertyAccessExpression:
+ case ts.SyntaxKind.PropertyAccessExpression: {
+ const symbol = this.checker.getSymbolAtLocation(
+ initializer as ts.PropertyAccessExpression
+ );
+
+ if (symbol && symbol.declarations.length) {
+ const declaration = symbol.declarations[0];
+
+ if (
+ ts.isBindingElement(declaration) ||
+ ts.isPropertyAssignment(declaration)
+ ) {
+ return this.getLiteralValueFromPropertyAssignment(declaration);
+ }
+ }
+ }
case ts.SyntaxKind.ObjectLiteralExpression:
default:
try {
@@ -881,26 +914,31 @@ export class Parser {
public getPropMap(
properties: ts.NodeArray
): StringIndexedObject {
- const propMap = properties.reduce((acc, property) => {
- if (ts.isSpreadAssignment(property) || !property.name) {
- return acc;
- }
+ const propMap = properties.reduce(
+ (acc, property) => {
+ if (ts.isSpreadAssignment(property) || !property.name) {
+ return acc;
+ }
- const literalValue = this.getLiteralValueFromPropertyAssignment(property);
- const propertyName = getPropertyName(property.name);
+ const literalValue = this.getLiteralValueFromPropertyAssignment(
+ property
+ );
+ const propertyName = getPropertyName(property.name);
- if (
- (typeof literalValue === 'string' ||
- typeof literalValue === 'number' ||
- typeof literalValue === 'boolean' ||
- literalValue === null) &&
- propertyName !== null
- ) {
- acc[propertyName] = literalValue;
- }
+ if (
+ (typeof literalValue === 'string' ||
+ typeof literalValue === 'number' ||
+ typeof literalValue === 'boolean' ||
+ literalValue === null) &&
+ propertyName !== null
+ ) {
+ acc[propertyName] = literalValue;
+ }
- return acc;
- }, {} as StringIndexedObject);
+ return acc;
+ },
+ {} as StringIndexedObject
+ );
return propMap;
}