This exploration documents how mint-tsdocs extracts, analyzes, and processes type information from API Extractor's .api.json files. The codebase uses a sophisticated multi-layered system combining API model traversal, recursive type string parsing, and semantic enrichment.
Two detailed reports have been created in /agent/reports/:
-
type-extraction-analysis.md (27 KB)
- Comprehensive 9-section analysis
- Full code snippets and explanations
- Deep dive into each component
- Examples of type processing flows
-
type-extraction-quick-reference.md (6 KB)
- Quick lookup guide
- File locations and entry points
- Type pattern detection
- Data flow examples
- Caching strategy overview
| Component | File | Purpose |
|---|---|---|
| MarkdownDocumenter | src/documenters/MarkdownDocumenter.ts | Orchestrates generation, recursively processes API items |
| TemplateDataConverter | src/templates/TemplateDataConverter.ts | Converts ApiItem objects to template-friendly data structures |
| ObjectTypeAnalyzer | src/utils/ObjectTypeAnalyzer.ts | Parses type strings (primitives, arrays, unions, objects, generics) |
| DocumentationHelper | src/utils/DocumentationHelper.ts | Enriches type analysis with semantic meaning and JSDoc descriptions |
Entry Point: param.parameterTypeExcerpt.text or apiItem.excerpt.text
Pipeline:
Type String (e.g., "{ name: string; config?: { enabled: boolean } }")
↓
ObjectTypeAnalyzer.analyzeType() [Recursive parsing]
↓
Detects pattern: object-literal
↓
_parseObjectLiteral() → Recursively extract properties
↓
For each property: analyzeType(propertyType) [Recursive call]
↓
DocumentationHelper enriches with descriptions
↓
Templates format for MDX output
The analyzer handles:
- Primitives: string, number, boolean, void, any, never, unknown, null, undefined
- Arrays: Type[] (recursive element analysis)
- Unions: Type1 | Type2 (recursive component analysis)
- Intersections: Type1 & Type2
- Generics: Base (extracts parameters)
- Object Literals: { prop: type; nested: { ... } } (recursive property extraction)
/work/mintlify-tsdocs/src/utils/ObjectTypeAnalyzer.ts(249 lines)analyzeType(type: string): TypeAnalysis(lines 41-53)_parseObjectLiteral(type: string): TypeAnalysis(lines 132-155)_parseProperties(content: string): PropertyAnalysis[](lines 160-186)_splitBySemicolons(content: string): string[](lines 191-217) - handles nested braces
/work/mintlify-tsdocs/src/templates/TemplateDataConverter.ts(345 lines)convertApiItem(apiItem, options): ITemplateData(lines 21-79)_createTableRows(apiItems, getLinkFilename): ITableRow[](lines 149-162)_createParameterRows(apiFunction, getLinkFilename): ITableRow[](lines 164-189)- Type-specific handlers:
_addClassData(),_addInterfaceData(), etc.
/work/mintlify-tsdocs/src/utils/DocumentationHelper.ts(179 lines)analyzeTypeProperties(type, description, propertyPath): PropertyInfo(lines 34-125)- Supports nested properties via recursive PropertyAnalysis
- Integrates JSDoc descriptions via propertyPath
/work/mintlify-tsdocs/src/documenters/MarkdownDocumenter.ts(2200+ lines)generateFiles(): Promise<void>(lines 189-227)_writeApiItemPageTemplate(apiItem, parentApiItem): Promise<void>(lines 241-322)- Recursively processes class/interface members
/work/mintlify-tsdocs/src/cache/TypeAnalysisCache.ts(148 lines)- LRU cache with 1000-item default capacity
- Hit/miss tracking for statistics
/work/mintlify-tsdocs/src/cache/ApiResolutionCache.ts(173 lines)- LRU cache for API reference resolution
For Classes/Interfaces:
// Member filtering by type
apiClass.members.filter(m => m.kind === ApiItemKind.Property)
apiInterface.members.filter(m => m.kind === ApiItemKind.PropertySignature)
// Type extraction
apiPropertyItem.propertyTypeExcerpt.text // Raw type string
ApiOptionalMixin.isOptional // Optional flag
ApiReadonlyMixin.isReadonly // Readonly flag
ApiInitializerMixin.initializerExcerpt // Default valueFor Parameters:
apiFunction.parameters // Array of ApiParameter objects
// Per parameter
param.parameterTypeExcerpt.text // Type string
param.isOptional // Optional flag
param.tsdocParamBlock // JSDoc @param docsRecursive Processing:
// Example: Nested object in parameter
param.parameterTypeExcerpt.text = "{ name: string; config: { enabled: boolean } }"
// Step 1: ObjectTypeAnalyzer detects object-literal
// Step 2: _parseObjectLiteral() extracts properties:
// - name (type: string, optional: false)
// - config (type: object-literal with nested properties)
// Step 3: Recursively analyze config's type
// Step 4: Build nested structure-
JSDoc Extraction (
JsDocExtractor.ts)- Hardcoded descriptions only
- Does not parse actual TypeScript source files
- Limited to predefined property paths
-
Type Linking (
TemplateDataConverter.ts:283-286)- Not implemented (returns
undefined) - Types don't resolve to their definitions
- Not implemented (returns
-
Generic Type Parameters
- Extracted but not deeply analyzed
- Type parameter constraints not extracted
Record<K, V>not fully resolved
-
Caching
- Simple string-based keys
- No TTL or auto-invalidation
- Maximum 1000 types by default
interface TypeAnalysis {
type: 'primitive' | 'array' | 'union' | 'intersection' | 'generic' | 'object-literal' | 'unknown';
name?: string;
elementType?: TypeAnalysis; // Arrays
unionTypes?: TypeAnalysis[]; // Unions
intersectionTypes?: TypeAnalysis[]; // Intersections
baseType?: string; // Generics
typeParameters?: string[]; // Generics
properties?: PropertyAnalysis[]; // Objects
}
interface PropertyAnalysis {
name: string;
type: TypeAnalysis; // Recursive
optional: boolean;
}interface PropertyInfo {
name: string;
type: string;
description: string;
required: boolean;
deprecated: boolean;
nestedProperties?: PropertyInfo[]; // Recursive
}interface ITableRow {
title: string;
titlePath?: string;
modifiers?: string[];
type?: string;
typePath?: string;
description?: string;
isOptional?: boolean;
isInherited?: boolean;
isDeprecated?: boolean;
defaultValue?: string;
}Input TypeScript:
function process(options: {
name: string;
timeout?: number;
handlers: {
onSuccess: (result: any) => void;
onError?: (error: Error) => void;
}[];
}): voidExtraction Flow:
MarkdownDocumenter._createParameterRows()getsparam.parameterTypeExcerpt.text- Type string:
"{ name: string; timeout?: number; handlers: { onSuccess: (result: any) => void; onError?: (error: Error) => void; }[]; }" ObjectTypeAnalyzer.analyzeType()parses as object-literal_parseObjectLiteral()extracts 3 properties:name(primitive: string, required)timeout(primitive: number, optional)handlers(array of object-literal)
- For
handlersarray: recursively analyze element type (object-literal with 2 methods) DocumentationHelper.analyzeTypeProperties()enriches with descriptions- Templates render parameter table with nested structure
Output Structure:
{
name: '',
type: 'object',
nestedProperties: [
{
name: 'name',
type: 'string',
required: true,
description: '...'
},
{
name: 'timeout',
type: 'number',
required: false,
description: '...'
},
{
name: 'handlers',
type: 'object[]',
required: true,
nestedProperties: [
{
name: 'onSuccess',
type: '(result: any) => void',
required: true
},
{
name: 'onError',
type: '(error: Error) => void',
required: false
}
]
}
]
}Caching:
- TypeAnalysisCache: 1000-item LRU for type analysis
- ApiResolutionCache: 500-item LRU for API reference resolution
- Both track hit/miss ratios
Statistics Available:
cache.getStats() → {
size: number;
maxSize: number;
hitRate: number;
hitCount: number;
missCount: number;
enabled: boolean;
}The type extraction system in mint-tsdocs is well-architected for documentation generation:
- Leverages API Extractor - Uses @microsoft/api-extractor-model for accurate type data
- Recursive Design - Handles nested objects, arrays, and complex types elegantly
- Caching for Performance - LRU caches reduce redundant analysis
- Semantic Enrichment - Adds descriptions and metadata beyond raw types
- Template Integration - Structured data designed for easy template rendering
- Parse actual TypeScript source for JSDoc descriptions
- Implement type linking to definitions
- Better handling of generic type parameters
- Circular reference detection
- Support for conditional/mapped types
Report Generated: November 19, 2025 Explored Files: 7 core files + 3 cache/utility files Total Code Analyzed: ~3,500+ lines of type extraction logic