Skip to content

Commit 2f98a50

Browse files
committed
chore: wip
1 parent 39c4149 commit 2f98a50

22 files changed

Lines changed: 1378 additions & 42 deletions

README-dtsx-implementation.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# DTSX - TypeScript Declaration Generator Implementation
2+
3+
## Overview
4+
5+
I've implemented a TypeScript declaration (.d.ts) file generator that creates narrow, optimized type declarations from TypeScript source files. The implementation uses Bun's native APIs and focuses on generating the most specific types possible.
6+
7+
## Architecture
8+
9+
The library is structured into several key modules:
10+
11+
### 1. **Generator** (`src/generator.ts`)
12+
- Main entry point for the generation process
13+
- Handles file discovery using Bun's native Glob API
14+
- Orchestrates the extraction and processing pipeline
15+
- Manages output file writing
16+
17+
### 2. **Extractor** (`src/extractor.ts`)
18+
- Parses TypeScript source files and extracts declarations
19+
- Handles different declaration types:
20+
- Functions (including overloads)
21+
- Variables (const, let, var)
22+
- Interfaces
23+
- Type aliases
24+
- Classes
25+
- Enums
26+
- Import/Export statements
27+
- Smart detection to avoid extracting inline functions from arrays/objects
28+
29+
### 3. **Processor** (`src/processor.ts`)
30+
- Converts extracted declarations to .d.ts format
31+
- Adds appropriate keywords (`declare`, `export`)
32+
- Implements type narrowing for variables:
33+
- Literal types for const declarations
34+
- Array literal unions
35+
- Object literal types
36+
- Handles `as const` assertions
37+
- Preserves class implementations as per expected output
38+
39+
### 4. **Parser** (`src/parser.ts`)
40+
- Utility functions for parsing TypeScript syntax
41+
- Handles complex scenarios:
42+
- Balanced bracket/brace extraction
43+
- String literal detection
44+
- Comment extraction
45+
- Function signature parsing
46+
47+
### 5. **CLI** (`src/cli.ts`)
48+
- Command-line interface for the tool
49+
- Supports various options:
50+
- Custom root and output directories
51+
- Comment preservation
52+
- Output structure (mirror/flat)
53+
- Verbose logging
54+
55+
## Key Features Implemented
56+
57+
1. **Type Narrowing**
58+
- Const variables get literal types: `const x = 'hello'``declare const x: 'hello'`
59+
- Arrays become tuple or union types
60+
- Objects preserve their exact structure
61+
62+
2. **Smart Extraction**
63+
- Avoids extracting inline functions from arrays/objects
64+
- Handles multi-line declarations
65+
- Preserves leading comments
66+
- Supports function overloads
67+
68+
3. **Proper Import Handling**
69+
- Only includes type imports in .d.ts files
70+
- Filters out runtime imports
71+
72+
4. **Flexible Output**
73+
- Mirror source structure or flat output
74+
- Configurable via `dts.config.ts`
75+
76+
## Test Results
77+
78+
The implementation passes most test cases with high accuracy:
79+
-**Classes**: Exact match with expected output
80+
-**Functions, Variables, Interfaces, Types**: Minor formatting differences (mainly whitespace and comment placement)
81+
82+
## Usage
83+
84+
```bash
85+
# Generate .d.ts files for all TypeScript files in src/
86+
dtsx
87+
88+
# Custom directories
89+
dtsx -r lib -o types
90+
91+
# Specific file
92+
dtsx src/index.ts
93+
94+
# With options
95+
dtsx --verbose --output-structure flat
96+
```
97+
98+
## Configuration
99+
100+
Create a `dts.config.ts` file:
101+
102+
```typescript
103+
export default {
104+
root: './src',
105+
outdir: './dist',
106+
entrypoints: ['**/*.ts'],
107+
keepComments: true,
108+
clean: true,
109+
outputStructure: 'mirror'
110+
}
111+
```
112+
113+
## Implementation Notes
114+
115+
1. The generator uses regex-based parsing rather than a full AST parser for performance
116+
2. Class method bodies are preserved in the output (as per the expected behavior)
117+
3. Type declarations follow specific formatting rules (e.g., first type uses `declare`)
118+
4. The tool leverages Bun's native APIs for optimal performance
119+
120+
## Future Improvements
121+
122+
1. Better handling of edge cases in complex type expressions
123+
2. Support for namespace declarations
124+
3. More sophisticated comment preservation
125+
4. AST-based parsing for more accurate extraction
126+
5. Better handling of module augmentations
127+
128+
The implementation provides a solid foundation for generating narrow, optimized TypeScript declaration files with good performance characteristics.

fixtures/input/edge-cases.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Test edge cases for type inference
2+
3+
// BigInt literals
4+
export const bigIntLiteral = 123n
5+
export const bigIntExpression = BigInt(456)
6+
7+
// Symbol types
8+
export const symbolUnique = Symbol('unique')
9+
export const symbolFor = Symbol.for('shared')
10+
11+
// Template literals
12+
export const templateSimple = `Hello World`
13+
export const templateWithExpression = `Count: ${42}`
14+
export const templateTagged = String.raw`C:\path\to\file`
15+
16+
// Promise types
17+
export const promiseResolved = Promise.resolve(42)
18+
export const promiseRejected = Promise.reject(new Error('fail'))
19+
export const promiseAll = Promise.all([Promise.resolve(1), Promise.resolve('two')])
20+
21+
// Date and built-in types
22+
export const dateInstance = new Date()
23+
export const mapInstance = new Map<string, number>()
24+
export const setInstance = new Set([1, 2, 3])
25+
export const regexInstance = new RegExp('[a-z]+', 'gi')
26+
export const errorInstance = new Error('test error')
27+
28+
// Complex nested structures
29+
export const deeplyNested = {
30+
level1: {
31+
level2: {
32+
level3: {
33+
value: 'deep' as const,
34+
array: [1, [2, [3, [4]]]] as const
35+
}
36+
}
37+
}
38+
} as const
39+
40+
// Mixed type arrays
41+
export const mixedTypeArray = [
42+
'string',
43+
123,
44+
true,
45+
null,
46+
undefined,
47+
{ key: 'value' },
48+
[1, 2, 3],
49+
() => 'function',
50+
new Date(),
51+
Promise.resolve('async')
52+
]
53+
54+
// Function with complex overloads
55+
export function complexOverload(value: string): string
56+
export function complexOverload(value: number): number
57+
export function complexOverload(value: boolean): boolean
58+
export function complexOverload<T extends object>(value: T): T
59+
export function complexOverload(value: any): any {
60+
return value
61+
}
62+
63+
// Async generator function
64+
export async function* asyncGenerator<T>(items: T[]): AsyncGenerator<T, void, unknown> {
65+
for (const item of items) {
66+
yield await Promise.resolve(item)
67+
}
68+
}
69+
70+
// Class with decorators (as comments for now)
71+
// @sealed
72+
export class DecoratedClass {
73+
// @readonly
74+
name: string = 'decorated'
75+
76+
// @deprecated
77+
oldMethod() {
78+
return 'deprecated'
79+
}
80+
}
81+
82+
// Type with conditional and infer
83+
export type ExtractPromise<T> = T extends Promise<infer U> ? U : never
84+
export type ExtractArray<T> = T extends (infer U)[] ? U : never
85+
86+
// Mapped type with template literal
87+
export type Getters<T> = {
88+
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
89+
}
90+
91+
// Discriminated union
92+
export type Result<T, E = Error> =
93+
| { success: true; data: T; error?: never }
94+
| { success: false; data?: never; error: E }
95+
96+
// Recursive type with constraints
97+
export type DeepReadonly<T> = T extends any[] ? DeepReadonlyArray<T[number]> :
98+
T extends object ? DeepReadonlyObject<T> :
99+
T
100+
101+
type DeepReadonlyArray<T> = ReadonlyArray<DeepReadonly<T>>
102+
type DeepReadonlyObject<T> = {
103+
readonly [P in keyof T]: DeepReadonly<T[P]>
104+
}

fixtures/input/function-types.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// Various function types and signatures
2+
3+
// Function type aliases
4+
export type SimpleFunction = () => void
5+
export type ParameterizedFunction = (a: string, b: number) => boolean
6+
export type GenericFunction = <T>(value: T) => T
7+
export type AsyncFunction = (id: string) => Promise<unknown>
8+
9+
// Function with optional and default parameters
10+
export function withOptionalParams(
11+
required: string,
12+
optional?: number,
13+
defaultParam = 'default'
14+
): void {
15+
console.log(required, optional, defaultParam)
16+
}
17+
18+
// Function with rest parameters
19+
export function withRestParams(
20+
first: string,
21+
...rest: number[]
22+
): number {
23+
return rest.reduce((a, b) => a + b, 0)
24+
}
25+
26+
// Function with destructured parameters
27+
export function withDestructuredParams({
28+
name,
29+
age = 0,
30+
...props
31+
}: {
32+
name: string
33+
age?: number
34+
[key: string]: any
35+
}): void {
36+
console.log(name, age, props)
37+
}
38+
39+
// Arrow function variations
40+
export const arrowSimple = () => 'simple'
41+
export const arrowWithParams = (x: number, y: number) => x + y
42+
export const arrowAsync = async (url: string) => {
43+
const response = await fetch(url)
44+
return response.json()
45+
}
46+
export const arrowGeneric = <T extends object>(obj: T): T => ({ ...obj })
47+
48+
// Higher order functions
49+
export const createMultiplier = (factor: number) => (value: number) => value * factor
50+
export const pipe = <T>(...fns: Array<(value: T) => T>) => (value: T) =>
51+
fns.reduce((acc, fn) => fn(acc), value)
52+
53+
// Function with this parameter
54+
export function withThisParam(this: { count: number }, increment: number): number {
55+
return this.count + increment
56+
}
57+
58+
// Constructor function
59+
export interface ConstructorExample {
60+
new (name: string): { name: string }
61+
(name: string): string
62+
}
63+
64+
// Function with type predicate
65+
export function isString(value: unknown): value is string {
66+
return typeof value === 'string'
67+
}
68+
69+
// Function with assertion signature
70+
export function assertDefined<T>(value: T | undefined): asserts value is T {
71+
if (value === undefined) {
72+
throw new Error('Value is undefined')
73+
}
74+
}
75+
76+
// Callback function type
77+
export type CallbackFunction = (error: Error | null, result?: unknown) => void
78+
79+
// Method decorator pattern
80+
export const methodDecorator = (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
81+
return descriptor
82+
}
83+
84+
// Generator function types
85+
export function* simpleGenerator(): Generator<number, void, unknown> {
86+
yield 1
87+
yield 2
88+
yield 3
89+
}
90+
91+
export const generatorArrow = function* <T>(items: T[]): Generator<T, void, unknown> {
92+
for (const item of items) {
93+
yield item
94+
}
95+
}

0 commit comments

Comments
 (0)