278 lines
5.0 KiB
Markdown
278 lines
5.0 KiB
Markdown
# Type From JSON
|
|
|
|
A CLI tool that automatically generates TypeScript type definitions from runtime API responses or JSON files.
|
|
|
|
## Features
|
|
|
|
- **JSON file type inference**: Read JSON files and generate TypeScript interfaces
|
|
- **Multiple response union type detection**: Detect union types when fields have different types across samples
|
|
- **Generate .d.ts files**: Output clean TypeScript declaration files
|
|
- **Watch mode**: Watch files and regenerate types on changes
|
|
- **CLI interface**: User-friendly command-line interface with commander.js
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Clone the repository
|
|
cd type-from-json
|
|
|
|
# Install dependencies
|
|
npm install
|
|
|
|
# Build the project
|
|
npm run build
|
|
|
|
# Install globally (optional)
|
|
npm install -g .
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Generate types from JSON files
|
|
|
|
```bash
|
|
# Generate .d.ts for a single file
|
|
type-from-json infer data.json
|
|
|
|
# Generate .d.ts for all JSON files matching a pattern
|
|
type-from-json infer "src/**/*.json"
|
|
|
|
# Specify output directory
|
|
type-from-json infer "*.json" --output ./types
|
|
|
|
# Specify custom interface name
|
|
type-from-json infer data.json --name MyCustomType
|
|
|
|
# Verbose output (shows generated types)
|
|
type-from-json infer data.json --verbose
|
|
```
|
|
|
|
### Watch mode
|
|
|
|
```bash
|
|
# Watch for file changes and regenerate types
|
|
type-from-json watch "src/**/*.json"
|
|
|
|
# Watch with output directory
|
|
type-from-json watch "src/**/*.json" --output ./types
|
|
|
|
# Watch with verbose output
|
|
type-from-json watch "data.json" --verbose
|
|
```
|
|
|
|
### Direct CLI options
|
|
|
|
```bash
|
|
# Using direct options
|
|
type-from-json -i "*.json" -o ./types -n MyType
|
|
|
|
# Watch mode via CLI
|
|
type-from-json -i "*.json" --watch
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Simple object
|
|
|
|
**Input (data.json):**
|
|
```json
|
|
{
|
|
"name": "John",
|
|
"age": 30,
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
**Output (data.d.ts):**
|
|
```typescript
|
|
export interface Data {
|
|
name: string;
|
|
age: number;
|
|
active: boolean;
|
|
}
|
|
```
|
|
|
|
### Nested objects
|
|
|
|
**Input (user.json):**
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"name": "Alice",
|
|
"address": {
|
|
"street": "123 Main St",
|
|
"city": "Boston"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Output (user.d.ts):**
|
|
```typescript
|
|
export interface User {
|
|
id: number;
|
|
name: string;
|
|
address: Address;
|
|
}
|
|
|
|
export interface Address {
|
|
street: string;
|
|
city: string;
|
|
}
|
|
```
|
|
|
|
### Arrays
|
|
|
|
**Input (items.json):**
|
|
```json
|
|
[
|
|
{ "id": 1, "name": "Item 1" },
|
|
{ "id": 2, "name": "Item 2" }
|
|
]
|
|
```
|
|
|
|
**Output (items.d.ts):**
|
|
```typescript
|
|
export type Items = {
|
|
id: number;
|
|
name: string;
|
|
}[];
|
|
```
|
|
|
|
### Union types
|
|
|
|
When analyzing multiple samples with different types:
|
|
|
|
**Input (response1.json):**
|
|
```json
|
|
{ "id": 1, "status": "active" }
|
|
```
|
|
|
|
**Input (response2.json):**
|
|
```json
|
|
{ "id": "abc", "status": "inactive" }
|
|
```
|
|
|
|
**Output:**
|
|
```typescript
|
|
export interface Response {
|
|
id: number | string;
|
|
status: "active" | "inactive";
|
|
}
|
|
```
|
|
|
|
### Optional fields
|
|
|
|
**Input (users.json):**
|
|
```json
|
|
[
|
|
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
|
|
{ "id": 2, "name": "Bob" }
|
|
]
|
|
```
|
|
|
|
**Output (users.d.ts):**
|
|
```typescript
|
|
export interface Users {
|
|
id: number;
|
|
name: string;
|
|
email?: string;
|
|
}
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### TypeInferrer
|
|
|
|
```typescript
|
|
import { TypeInferrer } from 'type-from-json';
|
|
|
|
const inferrer = new TypeInferrer({
|
|
rootName: 'MyType', // Optional: custom root type name
|
|
detectUnions: true, // Optional: detect union types (default: true)
|
|
literalThreshold: 3 // Optional: min occurrences for literal types
|
|
});
|
|
|
|
// Single JSON value
|
|
const result = inferrer.infer({ name: 'John', age: 30 });
|
|
|
|
// Multiple samples for union detection
|
|
const result = inferrer.inferFromMultiple([
|
|
{ id: 1 },
|
|
{ id: 'two' }
|
|
]);
|
|
```
|
|
|
|
### DeclarationGenerator
|
|
|
|
```typescript
|
|
import { DeclarationGenerator } from 'type-from-json';
|
|
|
|
const generator = new DeclarationGenerator(2); // 2-space indentation
|
|
|
|
// Generate from TypeDefinition array
|
|
const declaration = generator.generate(types);
|
|
|
|
// Generate standalone declaration
|
|
const standalone = generator.generateStandalone(types);
|
|
```
|
|
|
|
### FileWatcher
|
|
|
|
```typescript
|
|
import { FileWatcher } from 'type-from-json';
|
|
|
|
const watcher = new FileWatcher({
|
|
patterns: ['**/*.json'],
|
|
ignored: ['node_modules/**', 'dist/**'],
|
|
debounceMs: 300
|
|
});
|
|
|
|
await watcher.initialize();
|
|
|
|
watcher.start((event, filePath) => {
|
|
console.log(`${event}: ${filePath}`);
|
|
});
|
|
|
|
// Find files matching patterns
|
|
const files = await watcher.findFiles(['**/*.json']);
|
|
|
|
watcher.stop();
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `NODE_ENV` | Environment mode | `development` |
|
|
|
|
### TypeScript Configuration
|
|
|
|
The project uses ES2022 target with strict mode. Configuration is in `tsconfig.json`.
|
|
|
|
### Project Configuration (Optional)
|
|
|
|
Create a `type-from-json.config.json` in your project root:
|
|
|
|
```json
|
|
{
|
|
"outputDir": "./types",
|
|
"rootName": "ApiResponse",
|
|
"watchPatterns": ["src/**/*.json"],
|
|
"ignoredPatterns": ["node_modules/**", "dist/**"]
|
|
}
|
|
```
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Make your changes
|
|
4. Run tests: `npm test`
|
|
5. Submit a pull request
|
|
|
|
## License
|
|
|
|
MIT
|