diff --git a/.changeset/light-buckets-worry.md b/.changeset/light-buckets-worry.md new file mode 100644 index 0000000..7d1455e --- /dev/null +++ b/.changeset/light-buckets-worry.md @@ -0,0 +1,5 @@ +--- +"@tsxmod/utils": patch +--- + +Prints types for locally defined union members that come from `node_modules` in `getTypeDocumentation`. diff --git a/packages/utils/src/types/getTypeDocumentation.test.ts b/packages/utils/src/types/getTypeDocumentation.test.ts index d255361..25d6ee1 100644 --- a/packages/utils/src/types/getTypeDocumentation.test.ts +++ b/packages/utils/src/types/getTypeDocumentation.test.ts @@ -1909,4 +1909,66 @@ describe('getTypeDocumentation', () => { } `) }) + + test('printing imported node module union types', () => { + project.createSourceFile( + 'node_modules/library/index.d.ts', + dedent` + export type InterfaceMetadata = { + kind: 'Interface' + name: string + } + ` + ) + + const sourceFile = project.createSourceFile( + 'test.ts', + dedent` + import type { InterfaceMetadata } from 'library' + + export type TypeAliasMetadata = { + kind: 'TypeAlias' + name: string + } + + type AllMetadata = InterfaceMetadata | TypeAliasMetadata + `, + { overwrite: true } + ) + const types = getTypeDocumentation( + sourceFile.getTypeAliasOrThrow('AllMetadata') + ) + + expect(types).toMatchInlineSnapshot(` + { + "kind": "TypeAlias", + "name": "AllMetadata", + "properties": [], + "type": "InterfaceMetadata | TypeAliasMetadata", + "unionProperties": [ + [ + { + "type": "InterfaceMetadata", + }, + ], + [ + { + "defaultValue": undefined, + "description": undefined, + "name": "kind", + "required": true, + "type": "'TypeAlias'", + }, + { + "defaultValue": undefined, + "description": undefined, + "name": "name", + "required": true, + "type": "string", + }, + ], + ], + } + `) + }) }) diff --git a/packages/utils/src/types/getTypeDocumentation.ts b/packages/utils/src/types/getTypeDocumentation.ts index e70819a..55bc454 100644 --- a/packages/utils/src/types/getTypeDocumentation.ts +++ b/packages/utils/src/types/getTypeDocumentation.ts @@ -91,7 +91,7 @@ export interface ComponentMetadata extends SharedMetadata { export interface SharedPropertyMetadata extends SharedMetadata { defaultValue?: any - required: boolean + required?: boolean } export interface FunctionTypePropertyMetadata extends SharedPropertyMetadata { @@ -256,7 +256,6 @@ function processTypeAlias( const metadata: TypeAliasMetadata = { name, kind: 'TypeAlias', - name: typeAlias.getName(), properties: undefined as any, // Use the type node text if the name is the same as the type to provide a more accurate type type: nameIsSameAsType @@ -734,6 +733,9 @@ function processUnionType( propertyFilter?: PropertyFilter, defaultValues?: Record ) { + const unionTypeInNodeModules = getSymbolDeclaration(unionType.getSymbol()) + ?.getSourceFile() + .isInNodeModules() const allUnionTypes = unionType .getUnionTypes() .map((subType) => @@ -741,7 +743,8 @@ function processUnionType( subType, enclosingNode, propertyFilter, - defaultValues + defaultValues, + !unionTypeInNodeModules ) ) const { duplicates, filtered } = parseDuplicateTypes(allUnionTypes) @@ -757,7 +760,8 @@ function processTypeProperties( type: Type, enclosingNode?: Node, propertyFilter?: PropertyFilter, - defaultValues: Record = {} + defaultValues: Record = {}, + isUsedLocally = false ): PropertyMetadata[] { // Handle intersection types by recursively processing each type in the intersection if (type.isIntersection()) { @@ -768,16 +772,31 @@ function processTypeProperties( intersectType, enclosingNode, propertyFilter, - defaultValues + defaultValues, + isUsedLocally ) ) } const typeMetadata = getTypeMetadata(type, enclosingNode) - /** If no property filter is provided, short-circuit for types in node_modules. */ - if (!propertyFilter && typeMetadata.isInNodeModules) { - return [] + if (typeMetadata.isInNodeModules) { + /** If the node modules type is used locally, return the type text and the library that it is from. */ + if (isUsedLocally) { + return [ + { + type: type.getText( + enclosingNode, + TypeFormatFlags.UseAliasDefinedOutsideCurrentScope + ), + }, + ] + } + + /** If no property filter is provided, short-circuit for types in node_modules. */ + if (!propertyFilter) { + return [] + } } /**