From 261b36555542bb8e9a3ca027e34fa35f0f034dea Mon Sep 17 00:00:00 2001 From: Josemar Luedke Date: Fri, 16 Feb 2024 11:52:12 -0800 Subject: [PATCH] feat: handle function and objects in getPropertyType --- src/parser.ts | 102 ++++++++++++------ tests/__snapshots__/index.test.ts.snap | 139 ++++++++++++++++++++++++- tests/experiment.ts | 3 +- 3 files changed, 204 insertions(+), 40 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index c4dff14..74cdd06 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -183,23 +183,10 @@ export default class Parser { parentNode: ts.Node ): PropertyType { const typeAsString = this.checker.typeToString(type); - if ( - symbol && - isInterfaceOrObjectWithOptionalProperties(symbol) && - !/Element$/.test(symbol.getName()) - ) { - const props = type.getApparentProperties(); - return { - type: 'Object', - items: this.getPropertiesFromSymbols(props, parentNode) - }; - } - - if (type.isUnion() && typeAsString !== 'boolean') { + if (this.isInvokableType(type)) { return { - type: 'enum', - raw: typeAsString, - items: type.types.map((v) => this.getValuesFromUnionType(v)) + type: 'function', + raw: typeAsString }; } @@ -217,6 +204,33 @@ export default class Parser { }; } + if (type.isUnion() && typeAsString !== 'boolean') { + return { + type: 'enum', + raw: typeAsString, + items: type.types.map((v) => this.getValuesFromUnionType(v)) + }; + } + + if (this.isArrayType(type)) { + return { + type: 'Array', + raw: typeAsString + }; + } + + if ( + symbol && + this.isInterfaceOrObjectWithOptionalProperties(symbol, type) && + !/Element$/.test(symbol.getName()) + ) { + const props = type.getApparentProperties(); + return { + type: 'Object', + items: this.getPropertiesFromSymbols(props, parentNode) + }; + } + return { type: typeAsString }; @@ -230,8 +244,13 @@ export default class Parser { } isArrayType(type: ts.Type): boolean { - const kind = this.checker.getIndexTypeOfType(type, ts.IndexKind.Number); + const typeName = this.checker.typeToString(type); + if (typeName === 'string') { + return false; + } + + const kind = this.checker.getIndexTypeOfType(type, ts.IndexKind.Number); // Check if the type has a numeric index signature return !!kind; } @@ -308,28 +327,43 @@ export default class Parser { tags: tagMap }; } -} -function isInterfaceOrObjectWithOptionalProperties(symbol: ts.Symbol): boolean { - const declarations = symbol.declarations; - if (!declarations || declarations.length === 0) { - return false; - } + isInterfaceOrObjectWithOptionalProperties( + symbol: ts.Symbol, + type: ts.Type, + shallow = false + ): boolean { + const declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { + return false; + } - const declaration = declarations[0]; - if (!declaration) { - return false; - } + const declaration = declarations[0]; + if (!declaration) { + return false; + } - if (ts.isInterfaceDeclaration(declaration)) { - return true; - } + if (ts.isInterfaceDeclaration(declaration)) { + return true; + } - if (ts.isTypeLiteralNode(declaration)) { - return declaration.members.some((member) => ts.isPropertySignature(member)); - } + if (ts.isTypeLiteralNode(declaration)) { + return declaration.members.some((member) => + ts.isPropertySignature(member) + ); + } - return false; + const typeSymbol = type.getSymbol(); + if (!shallow && typeSymbol) { + const val = this.isInterfaceOrObjectWithOptionalProperties( + typeSymbol, + type, + true + ); + return val; + } + return false; + } } function extractPackageAndComponent(filePath: string): { diff --git a/tests/__snapshots__/index.test.ts.snap b/tests/__snapshots__/index.test.ts.snap index 9bf65b9..225d48d 100644 --- a/tests/__snapshots__/index.test.ts.snap +++ b/tests/__snapshots__/index.test.ts.snap @@ -271,7 +271,8 @@ It allows the consumer to render a link for example", "isRequired": true, "tags": {}, "type": { - "type": "(event: Event) => void", + "raw": "(event: Event) => void", + "type": "function", }, }, { @@ -589,7 +590,8 @@ option allows to choose where it appears from.", }, }, "type": { - "type": "() => void", + "raw": "() => void", + "type": "function", }, }, { @@ -656,7 +658,132 @@ option allows to choose where it appears from.", "isRequired": false, "tags": {}, "type": { - "type": "Transition", + "items": [ + { + "defaultValue": undefined, + "description": "", + "identifier": "didTransitionIn", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "raw": "() => void", + "type": "function", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "didTransitionOut", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "raw": "() => void", + "type": "function", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "enterClass", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "enterActiveClass", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "enterToClass", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "isEnabled", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "boolean", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "leaveClass", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "leaveActiveClass", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "leaveToClass", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "name", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + { + "defaultValue": undefined, + "description": "", + "identifier": "parentSelector", + "isInternal": false, + "isRequired": false, + "tags": {}, + "type": { + "type": "string", + }, + }, + ], + "type": "Object", }, }, ], @@ -705,7 +832,8 @@ option allows to choose where it appears from.", }, }, "type": { - "type": "() => void", + "raw": "() => void", + "type": "function", }, }, { @@ -764,7 +892,8 @@ option allows to choose where it appears from.", "isRequired": false, "tags": {}, "type": { - "type": "(key: string) => void", + "raw": "(key: string) => void", + "type": "function", }, }, ], diff --git a/tests/experiment.ts b/tests/experiment.ts index 4d12a99..85e5b56 100644 --- a/tests/experiment.ts +++ b/tests/experiment.ts @@ -25,7 +25,8 @@ function inspect(obj: unknown): void { // root: path.resolve(path.join(__dirname, '__fixtures__')), // pattern: 'test.js' root: path.resolve(path.join(__dirname, '../../frontile')), - pattern: 'packages/*/declarations/components/*.d.ts' + // pattern: 'packages/*/declarations/components/*.d.ts' + pattern: 'packages/overlays/declarations/components/popover.d.ts' } // { // options: {