Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inferring type from constrained generics #318

Merged
merged 1 commit into from
Jan 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/__tests__/data/GenericWithExtends.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//In our case we have a component that works like the foolowing

type SampleUnion = 'value 1' | 'value 2' | 'value 3' | 'value 4' | 'value n';
type SampleObject = {
propA: string;
propB: object;
propC: number;
};
class Base {
propA: string = 'A';
}
class SampleUnionNonGeneric extends Base {
propB: string = 'B';
}

export const GenericWithExtends = <
G extends SampleUnion,
A extends number[],
O extends { prop1: number }
>(props: {
/** sampleUnionProp description */
sampleUnionProp: G;
/** sampleUnionNonGeneric description */
sampleUnionNonGeneric: SampleUnionNonGeneric;
/** sampleObjectProp description */
sampleObjectProp: SampleObject;
/** sampleNumberProp description */
sampleNumberProp: number;
/** sampleGenericArray description */
sampleGenericArray: A;
/** sampleGenericObject description */
sampleGenericObject: O;
/** sampleInlineObject description */
sampleInlineObject: { propA: string };
}) => {
return <div>test</div>;
};
66 changes: 59 additions & 7 deletions src/__tests__/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ describe('parser', () => {
it('should parse react stateless component with generic intersection + union overlap props - simple', () => {
check('SimpleGenericUnionIntersection', {
SimpleGenericUnionIntersection: {
as: { type: 'T', description: '' },
as: { type: 'any', description: '' },
foo: {
description:
'The foo prop should not repeat the description\nThe foo prop should not repeat the description',
Expand All @@ -528,7 +528,7 @@ describe('parser', () => {
check('ComplexGenericUnionIntersection', {
ComplexGenericUnionIntersection: {
as: {
type: 'E',
type: 'ElementType<any>',
required: false,
description: 'Render the component as another component'
},
Expand Down Expand Up @@ -558,7 +558,7 @@ describe('parser', () => {
check('ComplexGenericUnionIntersectionWithOmit', {
ComplexGenericUnionIntersectionWithOmit: {
as: {
type: 'E',
type: 'ElementType<any>',
required: false,
description: 'Render the component as another component'
},
Expand Down Expand Up @@ -741,11 +741,11 @@ describe('parser', () => {
});
});

it("should parse functional component component defined as function as default export", () => {
check("FunctionDeclarationAsDefaultExport", {
it('should parse functional component component defined as function as default export', () => {
check('FunctionDeclarationAsDefaultExport', {
Jumbotron: {
prop1: { type: "string", required: true },
},
prop1: { type: 'string', required: true }
}
});
});

Expand Down Expand Up @@ -1104,6 +1104,58 @@ describe('parser', () => {
}
);
});

it('Should infer types from constraint type (generic with extends)', () => {
check(
'GenericWithExtends',
{
GenericWithExtends: {
sampleUnionProp: {
raw: 'SampleUnion',
type: 'enum',
value: [
{
value: '"value 1"'
},
{
value: '"value 2"'
},
{
value: '"value 3"'
},
{
value: '"value 4"'
},
{
value: '"value n"'
}
]
},
sampleUnionNonGeneric: {
type: 'SampleUnionNonGeneric'
},
sampleObjectProp: {
type: 'SampleObject'
},
sampleNumberProp: {
type: 'number'
},
sampleGenericArray: {
type: 'number[]'
},
sampleGenericObject: {
type: '{ prop1: number; }'
},
sampleInlineObject: {
type: '{ propA: string; }'
}
}
},
true,
null,
{ shouldExtractLiteralValuesFromEnum: true }
);
});
});

describe('Extracting values from unions', () => {
Expand Down
6 changes: 6 additions & 0 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,12 @@ export class Parser {
}

public getDocgenType(propType: ts.Type, isRequired: boolean): PropItemType {
// When we are going to process the type, we check if this type has a constraint (is a generic type with constraint)
if (propType.getConstraint()) {
// If so, we assing the property the type that is the constraint
propType = propType.getConstraint()!;
}

let propTypeString = this.checker.typeToString(propType);

if (propType.isUnion()) {
Expand Down