From 8e1740111987d9475770a8737d4d333e8a27a340 Mon Sep 17 00:00:00 2001 From: Andrew Lisowski Date: Wed, 4 Sep 2019 09:59:00 -0700 Subject: [PATCH] support typescript 3 style default props on function components --- .../StatelessWithDefaultPropsTypescript3.tsx | 48 +++++++++++++++++++ src/__tests__/parser.ts | 6 ++- src/parser.ts | 9 ++-- 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 src/__tests__/data/StatelessWithDefaultPropsTypescript3.tsx diff --git a/src/__tests__/data/StatelessWithDefaultPropsTypescript3.tsx b/src/__tests__/data/StatelessWithDefaultPropsTypescript3.tsx new file mode 100644 index 00000000..eaaabf25 --- /dev/null +++ b/src/__tests__/data/StatelessWithDefaultPropsTypescript3.tsx @@ -0,0 +1,48 @@ +import * as React from 'react'; + +export enum enumSample { + HELLO = 'hi', + BYE = 'bye' +} + +/** StatelessWithDefaultProps props */ +export interface StatelessWithDefaultPropsProps { + /** + * sample with default value + * @default hello + */ + sampleDefaultFromJSDoc: 'hello' | 'goodbye'; + /** sampleTrue description */ + sampleTrue: boolean; + /** sampleFalse description */ + sampleFalse: boolean; + /** sampleEnum description */ + sampleEnum: enumSample; + /** sampleString description */ + sampleString: string; + /** sampleObject description */ + sampleObject: { [key: string]: any }; + /** sampleNull description */ + sampleNull: null; + /** sampleUndefined description */ + sampleUndefined: any; + /** sampleNumber description */ + sampleNumber: number; +} + +/** StatelessWithDefaultProps description */ +export const StatelessWithDefaultProps: React.StatelessComponent< + StatelessWithDefaultPropsProps +> = props =>
test
; + +StatelessWithDefaultProps.defaultProps = { + sampleEnum: enumSample.HELLO, + sampleFalse: false, + sampleNull: null, + sampleNumber: -1, + // prettier-ignore + sampleObject: { a: '1', b: 2, c: true, d: false, e: undefined, f: null, g: { a: '1' } }, + sampleString: 'hello', + sampleTrue: true, + sampleUndefined: undefined +}; diff --git a/src/__tests__/parser.ts b/src/__tests__/parser.ts index 7d3404c9..d031fb3f 100644 --- a/src/__tests__/parser.ts +++ b/src/__tests__/parser.ts @@ -442,7 +442,7 @@ describe('parser', () => { regularProp: { defaultValue: 'foo', description: 'regularProp description', - required: true, + required: false, type: 'string' }, shorthandProp: { @@ -462,6 +462,10 @@ describe('parser', () => { it('supports destructuring for arrow functions', () => { check('StatelessWithDestructuredPropsArrow', expectation); }); + + it('supports typescript 3.0 style defaulted props', () => { + check('StatelessWithDefaultPropsTypescript3', expectation); + }); }); it('should parse functional component component defined as function', () => { diff --git a/src/parser.ts b/src/parser.ts index cd270bf2..95c0681a 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -135,9 +135,7 @@ export function withCustomConfig( ); if (error !== undefined) { - 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); } @@ -508,10 +506,11 @@ export class Parser { const isOptional = (prop.getFlags() & ts.SymbolFlags.Optional) !== 0; const jsDocComment = this.findDocComment(prop); + const hasCodeBasedDefault = defaultProps[propName] !== undefined; let defaultValue = null; - if (defaultProps[propName] !== undefined) { + if (hasCodeBasedDefault) { defaultValue = { value: defaultProps[propName] }; } else if (jsDocComment.tags.default) { defaultValue = { value: jsDocComment.tags.default }; @@ -524,7 +523,7 @@ export class Parser { description: jsDocComment.fullComment, name: propName, parent, - required: !isOptional, + required: !isOptional && !hasCodeBasedDefault, type: this.getDocgenType(propType) }; });