A TypeScript schema generation tool that extracts Zod schemas from TypeScript source files with runtime validation support. Generate validation schemas directly from your existing TypeScript types with support for computed types and constraint-based validation.
npm install typescript-runtime-schemas
- 🎯 Schema File Generation: Extract Zod schemas directly from TypeScript source files
- 🔧 CLI Tool: Command-line interface for batch processing and file generation
- 🚀 Computed Types Support: Full support for utility types like
Pick
,Omit
,Partial
,Required
, etc. - 📝 Constraint Types: Use TypeScript intersection types for validation constraints
- 🔍 Runtime Validation: Generate Zod schemas with runtime validation support
- 📦 Programmatic API: Full API for integration into your build process
- 📝 Type Safety: Full TypeScript support with proper type definitions
For schema generation to work, your types must extend SupportsRuntimeValidation
:
import {
Min,
Max,
Email,
UUID,
MinLength,
SupportsRuntimeValidation,
} from "typescript-runtime-schemas";
// ✅ This type will be processed for schema generation
type User = {
id: string & UUID;
email: string & Email;
age: number & Min<18> & Max<120>;
name: string & MinLength<2>;
} & SupportsRuntimeValidation;
// ✅ Interface extending SupportsRuntimeValidation
interface Product extends SupportsRuntimeValidation {
id: string & UUID;
name: string & MinLength<1>;
price: number & Min<0>;
}
// ❌ This type will be ignored (no SupportsRuntimeValidation)
type IgnoredType = {
id: string;
name: string;
};
# Generate schemas from a single file
npx typescript-runtime-schemas generate ./src/types.ts --output ./schemas
# Generate schemas from entire directory
npx typescript-runtime-schemas generate ./src --output ./schemas --structured
# List types that support runtime validation
npx typescript-runtime-schemas list ./src/types.ts
Schema Gen fully supports TypeScript utility types:
import {
UUID,
Email,
Min,
SupportsRuntimeValidation,
} from "typescript-runtime-schemas";
// Base type
type BaseUser = {
id: string & UUID;
email: string & Email;
name: string;
age: number & Min<18>;
role: string;
createdAt: Date;
} & SupportsRuntimeValidation;
// ✅ Pick utility type - generates schema for selected fields only
type UserProfile = Pick<BaseUser, "id" | "name" | "email"> &
SupportsRuntimeValidation;
// ✅ Omit utility type - generates schema excluding specified fields
type CreateUserRequest = Omit<BaseUser, "id" | "createdAt"> &
SupportsRuntimeValidation;
// ✅ Partial utility type - makes all fields optional
type UpdateUserRequest = Partial<BaseUser> & SupportsRuntimeValidation;
// ✅ Complex combinations
type UserSummary = Pick<BaseUser, "id" | "name"> & {
lastLogin: Date;
} & SupportsRuntimeValidation;
Generated schemas will be:
// UserProfile schema
z.object({
id: z.string().uuid(),
name: z.string(),
email: z.string().email(),
});
// CreateUserRequest schema
z.object({
email: z.string().email(),
name: z.string(),
age: z.number().min(18),
role: z.string(),
});
// UpdateUserRequest schema (all fields optional)
z.object({
id: z.string().uuid().optional(),
email: z.string().email().optional(),
name: z.string().optional(),
age: z.number().min(18).optional(),
role: z.string().optional(),
createdAt: z.date().optional(),
});
# Basic file generation
npx typescript-runtime-schemas generate <input> --output <output>
# Generate structured output (one schema file per source file)
npx typescript-runtime-schemas generate ./src --output ./schemas --structured
# Use configuration file for complex setups
npx typescript-runtime-schemas generate --config ./my-config.js
# Options
--output, -o Output directory or file
--structured Create structured output (one file per source file)
--format Output format (zod, json) [default: zod]
--include Include glob patterns
--exclude Exclude glob patterns
--config <file> Configuration file path
You can optionally create a typescript-runtime-schemas.config.js
file in your project root to set default options and avoid repeating command-line arguments:
module.exports = {
input: "./src/**/*.ts",
output: "./schemas",
structured: true,
format: "zod",
exclude: ["**/*.test.ts", "**/*.spec.ts"],
};
The CLI will automatically look for config files in this order:
typescript-runtime-schemas.config.js
typescript-runtime-schemas.config.json
typescript-runtime-schemas.config.mjs
Command-line options always take precedence over config file settings.
# List all types that support runtime validation
npx typescript-runtime-schemas list ./src/types.ts
# List types in directory recursively
npx typescript-runtime-schemas list ./src --recursive
# Extract type information as JSON
npx typescript-runtime-schemas extract ./src/types.ts --format json
# Parallel processing options for large codebases
npx typescript-runtime-schemas extract ./src --concurrency 8 --progress
npx typescript-runtime-schemas extract ./src --chunk-size 50 --no-parallel
# Get statistics about types and validation support
npx typescript-runtime-schemas stats ./src
Important: Only types that extend SupportsRuntimeValidation
will be processed for schema generation!
This is a design decision to ensure explicit opt-in for runtime validation.
import {
SupportsRuntimeValidation,
Email,
Min,
} from "typescript-runtime-schemas";
// ✅ Correct - intersection with SupportsRuntimeValidation
type User = {
email: string & Email;
age: number & Min<18>;
} & SupportsRuntimeValidation;
// ❌ Incorrect - will be ignored
type IgnoredUser = {
email: string & Email;
age: number & Min<18>;
};
import {
SupportsRuntimeValidation,
Email,
Min,
} from "typescript-runtime-schemas";
// ✅ Correct - extends SupportsRuntimeValidation
interface User extends SupportsRuntimeValidation {
email: string & Email;
age: number & Min<18>;
}
// ❌ Incorrect - will be ignored
interface IgnoredUser {
email: string & Email;
age: number & Min<18>;
}
// ✅ Computed types must also extend SupportsRuntimeValidation
type UserProfile = Pick<User, "email"> & SupportsRuntimeValidation;
type CreateUser = Omit<User, "id"> & SupportsRuntimeValidation;
Schema Gen provides full support for TypeScript utility types:
-
Pick<T, K>
- Select specific properties -
Omit<T, K>
- Exclude specific properties -
Partial<T>
- Make all properties optional -
Required<T>
- Make all properties required -
Readonly<T>
- Make all properties readonly
-
Exclude<T, U>
- Exclude types from union -
Extract<T, U>
- Extract types from union -
NonNullable<T>
- Remove null and undefined
-
ReturnType<T>
- Extract function return type -
Parameters<T>
- Extract function parameter types -
ConstructorParameters<T>
- Extract constructor parameter types -
InstanceType<T>
- Extract instance type from constructor
-
Record<K, V>
- Create object type with specific keys and values - Complex intersections and unions
import {
Min,
Max,
Integer,
Positive,
Negative,
Range,
} from "typescript-runtime-schemas";
type Product = {
price: number & Positive & Min<0.01>;
quantity: number & Integer & Min<0>;
rating: number & Range<1, 5>;
} & SupportsRuntimeValidation;
import {
MinLength,
MaxLength,
Email,
UUID,
URL,
Regex,
} from "typescript-runtime-schemas";
type User = {
email: string & Email;
id: string & UUID;
website: string & URL;
username: string & MinLength<3> & MaxLength<20>;
phone: string & Regex<"^\\+?[1-9]\\d{1,14}$">;
} & SupportsRuntimeValidation;
import { MinLength, MaxLength } from "typescript-runtime-schemas";
type Team = {
members: string[] & MinLength<1> & MaxLength<10>;
} & SupportsRuntimeValidation;
import {
Phone,
CreditCard,
IPAddress,
Base64,
} from "typescript-runtime-schemas";
type Contact = {
phone: string & Phone;
ip: string & IPAddress;
avatar: string & Base64;
} & SupportsRuntimeValidation;
For advanced use cases, you can use the programmatic API:
Extract schemas from various sources:
import { SchemaExtractor } from "typescript-runtime-schemas";
// From source code string
const schemas = await SchemaExtractor.extractZodSchemas(sourceCode);
// From file
const schemas = await SchemaExtractor.extractZodSchemasFromFile("./types.ts");
// From directory
const schemas = await SchemaExtractor.extractZodSchemasFromDirectory("./src");
// Extract and write to files
await SchemaExtractor.extractAndWriteZodSchemas(sourceCode, "./output");
Resolve complex TypeScript types including computed types:
import { TypeResolver } from "typescript-runtime-schemas";
const resolver = new TypeResolver(sourceCode);
const resolvedTypes = resolver.resolveTypes(["User", "Product"]);
Generate Zod schemas from parsed types:
import { ZodSchemaGenerator } from "typescript-runtime-schemas";
const schemas = ZodSchemaGenerator.generateSchemas(parsedTypes);
The package provides multiple import paths for different use cases:
// Import everything (constraint types + API)
import {
Min,
Max,
SchemaExtractor,
SupportsRuntimeValidation,
} from "typescript-runtime-schemas";
// Import only constraint types
import {
Min,
Max,
Email,
UUID,
SupportsRuntimeValidation,
} from "typescript-runtime-schemas/types";
// Import only the programmatic API
import { SchemaExtractor, TypeResolver } from "typescript-runtime-schemas/api";
import {
Min,
Max,
Email,
SupportsRuntimeValidation,
} from "typescript-runtime-schemas";
type User = {
id: number & Min<1>;
email: string & Email;
age: number & Min<0> & Max<150>;
} & SupportsRuntimeValidation;
// Generated Zod schema:
// z.object({
// id: z.number().min(1),
// email: z.string().email(),
// age: z.number().min(0).max(150)
// })
import {
MinLength,
UUID,
Positive,
SupportsRuntimeValidation,
} from "typescript-runtime-schemas";
type Order = {
id: string & UUID;
items: OrderItem[] & MinLength<1>;
total: number & Positive;
} & SupportsRuntimeValidation;
type OrderItem = {
productId: string & UUID;
quantity: number & Min<1>;
price: number & Positive;
} & SupportsRuntimeValidation;
// Create computed types for different use cases
type CreateOrderRequest = Omit<Order, "id"> & SupportsRuntimeValidation;
type OrderSummary = Pick<Order, "id" | "total"> & SupportsRuntimeValidation;
type UpdateOrderRequest = Partial<Pick<Order, "items" | "total">> &
SupportsRuntimeValidation;
// build-schemas.ts
import { SchemaExtractor } from "typescript-runtime-schemas";
import { glob } from "fast-glob";
async function buildSchemas() {
const files = await glob("./src/**/*.ts");
for (const file of files) {
await SchemaExtractor.extractAndWriteZodSchemasFromFile(
file,
"./generated/schemas"
);
}
}
buildSchemas().catch(console.error);
Schema Gen automatically optimizes performance for large codebases using parallel processing:
- Small codebases (≤10 types): Sequential processing for minimal overhead
- Large codebases (>10 types): Automatic parallel processing with optimal concurrency
- Progress tracking: Real-time progress updates for long-running operations
- Memory management: Adaptive concurrency based on memory usage
# Control concurrency (default: number of CPU cores)
npx typescript-runtime-schemas extract ./src --concurrency 4
# Process in chunks for memory efficiency
npx typescript-runtime-schemas extract ./src --chunk-size 100
# Disable parallel processing
npx typescript-runtime-schemas extract ./src --no-parallel
# Enable progress tracking
npx typescript-runtime-schemas extract ./src --progress
# Memory-aware processing
npx typescript-runtime-schemas extract ./src --max-memory 512
import { SchemaExtractor } from "typescript-runtime-schemas";
const result = await SchemaExtractor.extract(input, {
parallel: {
concurrency: 8, // Number of concurrent workers
useParallelProcessing: true, // Enable/disable parallel processing
chunkSize: 50, // Process types in chunks
enableProgressTracking: true, // Enable progress callbacks
maxMemoryMB: 512, // Memory limit for adaptive concurrency
onProgress: (progress) => {
// Progress callback with timing information
console.log(`${progress.percentage}% complete`);
console.log(`ETA: ${progress.eta}ms`);
console.log(`Rate: ${progress.rate} types/sec`);
},
},
});
- 2-4x faster processing on multi-core systems for large codebases
- Memory efficient chunked processing with adaptive concurrency
- Graceful error handling - failed types don't stop the entire process
- Progress tracking with ETA and processing rate information
- Automatic optimization - switches between sequential and parallel based on workload size
- Semaphore-based concurrency control - prevents resource exhaustion
Ensure your tsconfig.json
includes:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strict": true
}
}
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
MIT License - see the LICENSE file for details.