@flink-app/ts-source-to-json-schema
v0.1.6
Published
A zero-dependency TypeScript-to-JSON Schema converter that uses its own mini-parser
Downloads
965
Readme
ts-to-jsonschema
A zero-dependency TypeScript-to-JSON Schema converter that uses its own mini-parser instead of the TypeScript compiler.
It parses TypeScript type declarations (interfaces, type aliases, enums) directly from source strings and emits JSON Schema (2020-12 draft). No ts.createProgram, no node_modules bloat, no compiler startup cost.
Why
Existing tools like ts-json-schema-generator and typescript-json-schema rely on the full TypeScript compiler API to resolve types. That works, but it's slow, heavy, and ties you to Node.js. Furthermore, these libraries might need significant rewrites when TypeScript 7 (tsgo) is released, making their long-term future uncertain.
This library takes a different approach: instead of running the type checker, it tokenizes and parses a practical subset of TypeScript's type syntax directly. The result is a tool that's fast enough to run in a hot path, portable enough to run anywhere (Cloudflare Workers, browser, CLI), and simple enough to extend.
The trade-off is explicit: it handles the type constructs you'd actually use in API contracts, tool schemas, and config definitions — not the full type-level programming language.
What it handles
- Declarations:
interface,type,enum(string + numeric),export - Primitives:
string,number,boolean,null,undefined,any,unknown,never,void,bigint - Built-in types:
Date→{ type: "string", format: "date-time" } - Literal types:
"active",42,true - Unions:
A | B | C→anyOf(orenumwhen all members are literals) - Intersections:
A & B→allOf - Arrays:
T[],Array<T>, nestedT[][] - Tuples:
[string, number]→prefixItems - Nullable:
string | null→type: ["string", "null"] - Nested objects: inline
{ foo: string }and cross-references via$ref - Self-referential types:
Taskcontainingsubtasks: Task[] - Interface extends:
interface Dog extends Animal→allOf - Index signatures:
[key: string]: T→additionalProperties - Generic type instantiation:
interface Foo extends Generic<TypeArg>→ inlines with type parameter substitution- Supports interfaces and type aliases with type arguments
- Handles nested generics:
Box<Box<string>> - Multiple type parameters:
Pair<T, U> - Type parameters are substituted throughout properties, arrays, unions, etc.
- Falls back to
$refwhen generic definition is not found
- Utility types:
Partial<T>,Required<T>,Pick<T, K>,Omit<T, K>,Record<K, V>,Readonly<T>,Set<T>,Map<K, V>,Promise<T>(unwrapped) - Local imports: Automatic resolution of relative imports (
./and../) across files - JSDoc:
/** description */→description, plus tags:@minimum,@maximum,@minLength,@maxLength,@pattern,@format,@default,@deprecated,@title,@example,@additionalProperties - Readonly:
readonly→readOnlyin schema
Installation
npm install ts-source-to-json-schemaCLI Usage
The package includes a command-line tool for converting TypeScript files to JSON Schema:
# Convert a TypeScript file
npx ts-source-to-json-schema src/types.ts
# Convert with automatic import resolution (default)
npx ts-source-to-json-schema src/api.ts
# Convert a specific type as the root schema
npx ts-source-to-json-schema src/api.ts --rootType ApiResponse
# Use strict mode (no additional properties allowed)
npx ts-source-to-json-schema src/config.ts --strictObjects
# Disable JSDoc processing
npx ts-source-to-json-schema src/types.ts --includeJSDoc false
# Single file mode, no imports
npx ts-source-to-json-schema src/types.ts --followImports none
# Combine multiple options
npx ts-source-to-json-schema src/user.ts -r User --strictObjects --followImports localCLI Options
-h, --help Show help message
-v, --version Show version number
--doctor Output diagnostic information for debugging
--batch Batch mode: generate schemas for all types across files
-r, --rootType <name> Emit this type as root (others in $defs)
-s, --includeSchema <bool> Include $schema property (default: true)
--schemaVersion <url> Custom $schema URL
--strictObjects Set additionalProperties: false globally
--additionalProperties Set additionalProperties default (true/false)
--includeJSDoc <bool> Include JSDoc comments (default: true)
--followImports <mode> Follow imports: none, local, all (default: local)
--baseDir <path> Base directory for resolving importsThe CLI reads TypeScript files and outputs JSON Schema to stdout, making it easy to pipe to files or other tools:
# Save to file
npx ts-source-to-json-schema src/types.ts > schema.json
# Pretty-print with jq
npx ts-source-to-json-schema src/types.ts | jq '.'
# Use in scripts
npx ts-source-to-json-schema src/api.ts --rootType Request > openapi/request-schema.jsonMulti-File Support (--followImports)
By default, the CLI automatically follows local relative imports (./ and ../) to resolve type definitions across multiple files:
// pet.ts
export interface Pet {
_id: string;
name: string;
species: string;
}
// api.ts
import { Pet } from './pet';
export interface PostPetReq extends Omit<Pet, "_id"> {}# Follows imports and resolves Pet type (default behavior)
npx ts-source-to-json-schema api.ts --rootType PostPetReq
# Output includes both Pet (in $defs) and PostPetReq (as root)Import Resolution Modes:
local(default in CLI): Follows relative imports (./and../), skipsnode_modulesnone: Single-file mode, does not follow any importsall: Reserved for futurenode_modulessupport (currently behaves likelocal)
Key Features:
- Circular dependency detection (no infinite loops)
- Duplicate name detection (errors if same type name in multiple files)
- Automatic extension resolution (
.ts,.tsx,.d.ts) - Index file support (
./types→./types/index.ts)
Examples:
# Multi-file project with local imports
npx ts-source-to-json-schema src/api.ts --followImports local
# Single file only, ignore imports
npx ts-source-to-json-schema src/standalone.ts --followImports none
# Custom base directory for import resolution
npx ts-source-to-json-schema src/api.ts --baseDir ./srcBatch Mode (--batch)
Use --batch to generate schemas for all types across multiple files at once. Accepts glob patterns or multiple file paths:
# Batch: all schemas from matching files
npx ts-source-to-json-schema --batch 'src/schemas/**/*.ts' --followImports local
# Batch: specific files
npx ts-source-to-json-schema --batch src/PostReq.ts src/PostRes.ts --followImports local
# Batch with strict objects
npx ts-source-to-json-schema --batch 'src/types/*.ts' --strictObjectsOutput is a JSON object where keys are type names and values are standalone schemas:
{
"PostReq": { "$schema": "...", "type": "object", "properties": { ... } },
"PostRes": { "$schema": "...", "type": "object", "properties": { ... } }
}Shared imports are resolved once and deduplicated across all entry files.
Diagnostics Mode (--doctor)
When you encounter issues with schema conversion, use the --doctor flag to output comprehensive diagnostic information that can be shared with developers:
npx ts-source-to-json-schema src/problematic-types.ts --doctorThe doctor output includes:
- Timestamp: When the conversion was attempted
- Environment: Node.js version, platform, architecture, and current working directory
- Input file details: Path, existence, size, modification time, source length, and full source code
- Options used: All configuration options passed to the converter
- Conversion result: Either the successfully generated schema or detailed error information with stack traces
This makes it easy to:
- Copy-paste the full diagnostic output when reporting issues
- Debug why a particular TypeScript file isn't converting as expected
- Share reproducible examples with maintainers
Example output:
{
"timestamp": "2026-02-25T10:50:55.680Z",
"environment": {
"nodeVersion": "v20.17.0",
"platform": "darwin",
"arch": "arm64",
"cwd": "/path/to/project"
},
"input": {
"filePath": "types.ts",
"absolutePath": "/absolute/path/to/types.ts",
"fileExists": true,
"fileSize": 486,
"sourceLength": 486,
"source": "interface User { ... }"
},
"options": { "rootType": "User" },
"conversionResult": {
"success": true,
"schema": { ... }
}
}Programmatic Usage
String-Based API
import { toJsonSchema } from "ts-source-to-json-schema";
const schema = toJsonSchema(`
/** Input for the ad analysis tool */
interface AnalyzeAdInput {
/** URL of the ad to analyze */
url: string;
/** Platform the ad is from */
platform: "instagram" | "facebook" | "tiktok";
/** Whether to extract color palette */
extractColors?: boolean;
/** Max elements to identify
* @minimum 1
* @maximum 50
* @default 10
*/
maxElements?: number;
tags: string[];
}
`, { rootType: "AnalyzeAdInput" });File-Based API with Import Resolution
import { toJsonSchemaFromFile } from "ts-source-to-json-schema";
// Convert a TypeScript file with automatic import resolution
const schema = toJsonSchemaFromFile('./src/types/api.ts', {
followImports: 'local', // Follow relative imports
rootType: 'ApiRequest',
strictObjects: true
});
// Single-file mode (no import resolution)
const singleFileSchema = toJsonSchemaFromFile('./src/types.ts', {
followImports: 'none'
});Batch Schema Generation
When you need schemas for multiple types from the same source file, use toJsonSchemas() (plural) for better performance. This is particularly useful for build tools, documentation generators, or API schema validators that process many types at once.
import { toJsonSchemas } from "ts-source-to-json-schema";
const source = `
export interface User { id: string; name: string; }
export interface Post { id: string; title: string; author: User; }
export interface Comment { id: string; text: string; }
`;
// Generate all schemas at once (~70% faster than calling toJsonSchema() for each type)
const schemas = toJsonSchemas(source);
console.log(schemas.User); // Standalone User schema
console.log(schemas.Post); // Post schema with User in definitions
console.log(schemas.Comment); // Standalone Comment schemaKey benefits:
- Performance: ~70% faster when generating 30+ schemas from the same source
- Single parse: Source is tokenized and parsed only once
- Standalone schemas: Each schema includes only the types it references in its
definitionsfield - Self-contained: Each schema includes
$schemafield by default for better IDE validation - Draft-07 compatible: Uses
definitionsinstead of$defsfor broader compatibility
How it works:
- Parses the source once and emits all type declarations
- Each schema is standalone with minimal
definitions(only transitively referenced types) - Uses
#/definitions/TypeNamerefs instead of#/$defs/TypeName - Handles circular references, transitive dependencies, and utility types
Use cases:
- Framework integrations (like Flink) that need many schemas from one source
- Build tools generating schemas for entire API definition files
- Documentation generators processing large type files
- Schema validation libraries caching multiple schemas
Example with real-world API:
const schemas = toJsonSchemas(`
interface User { id: string; name: string; }
interface CreateUserRequest { name: string; }
interface CreateUserResponse { user: User; }
interface GetUserRequest { id: string; }
interface GetUserResponse { user: User; }
`, { includeJSDoc: true, strictObjects: true });
// Extract specific schemas as needed
const requestSchemas = {
CreateUser: schemas.CreateUserRequest,
GetUser: schemas.GetUserRequest
};Batch Generation with Import Resolution
If your types are spread across multiple files with imports, use toJsonSchemasFromFile() (the file-based batch API):
import { toJsonSchemasFromFile } from "ts-source-to-json-schema";
// Intermediate schema file (e.g., generated by a framework)
// schemas.ts:
// import TreeNode from "../../src/schemas/TreeNode";
// import Car from "../../src/schemas/Car";
// export interface GetTree_12_ResSchema extends TreeNode {}
// export interface GetCar_10_ResSchema extends Car {}
const schemas = toJsonSchemasFromFile('./schemas.ts', {
followImports: 'local', // Resolve relative imports
strictObjects: true
});
console.log(schemas.GetTree_12_ResSchema);
// {
// "$ref": "#/definitions/TreeNode",
// "definitions": {
// "TreeNode": { "type": "object", ... } // ✅ Included from imported file!
// }
// }Why use toJsonSchemasFromFile()?
- Automatically resolves imports from local files
- Generates batch schemas for all types (like
toJsonSchemas()) - Handles circular dependencies across files
- Perfect for framework integrations (like Flink) with generated intermediate files
Performance: Same batch performance benefits as toJsonSchemas(), plus automatic import resolution.
Multi-Entry Batch Generation
When you need to generate schemas from multiple TypeScript files (not just one entry file), use toJsonSchemasFromFiles(). It accepts a glob pattern or an array of file paths:
import { toJsonSchemasFromFiles } from "ts-source-to-json-schema";
// Glob pattern — matches all .ts files in src/schemas/
const schemas = toJsonSchemasFromFiles('src/schemas/**/*.ts', {
followImports: 'local'
});
// Array of specific files
const schemas = toJsonSchemasFromFiles([
'src/schemas/PostUserReq.ts',
'src/schemas/PostUserRes.ts'
], { followImports: 'local' });
// With defineNameTransform for namespacing
const schemas = toJsonSchemasFromFiles('src/schemas/**/*.ts', {
followImports: 'local',
defineNameTransform: (name, decl, ctx) => {
const file = path.basename(ctx?.relativePath ?? '', '.ts');
return `${file}.${name}`;
}
});Key benefits over toJsonSchemasFromFile():
- Accepts multiple entry files or a glob pattern (not just a single file)
- Shared imports are resolved once and deduplicated across all entry files
- Combined with
defineNameTransform, enables stable type IDs across all schemas - Returns
{}when no files match (safe for empty globs)
Glob support:
*matches any characters within a file/directory name**matches zero or more directory levels?matches a single character
Output:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"description": "Input for the ad analysis tool",
"properties": {
"url": { "type": "string", "description": "URL of the ad to analyze" },
"platform": {
"type": "string",
"enum": ["instagram", "facebook", "tiktok"],
"description": "Platform the ad is from"
},
"extractColors": { "type": "boolean", "description": "Whether to extract color palette" },
"maxElements": {
"type": "number",
"description": "Max elements to identify",
"minimum": 1,
"maximum": 50,
"default": 10
},
"tags": { "type": "array", "items": { "type": "string" } }
},
"required": ["url", "platform", "tags"]
}Options
toJsonSchema(source, {
rootType: "MyType", // Emit this type as the root schema (others go in $defs)
includeSchema: true, // Include $schema field (default: true)
strictObjects: false, // Set additionalProperties: false on all objects
schemaVersion: "https://json-schema.org/draft/2020-12/schema",
includeJSDoc: true, // Include JSDoc descriptions and tags (default: true)
additionalProperties: undefined, // Default value for additionalProperties (undefined, true, or false)
});
toJsonSchemaFromFile(filePath, {
// All options from toJsonSchema, plus:
followImports: 'local', // Follow imports: 'none' (default for API), 'local' (default for CLI), 'all'
baseDir: './src', // Base directory for resolving imports (default: dirname(filePath))
onDuplicateDeclarations: 'error', // Handle duplicate type names: 'error' (default), 'warn', 'silent'
});
toJsonSchemasFromFile(filePath, {
// All options from toJsonSchemas, plus:
followImports: 'local', // Follow imports: 'none', 'local' (default), 'all'
baseDir: './src', // Base directory for resolving imports (default: dirname(filePath))
onDuplicateDeclarations: 'error', // Handle duplicate type names: 'error' (default), 'warn', 'silent'
// Note: rootType is not supported (generates schemas for all types)
});
toJsonSchemasFromFiles(entries, {
// entries: glob pattern (string) or array of file paths
// All options from toJsonSchemas, plus:
followImports: 'local', // Follow imports: 'none' (default), 'local', 'all'
baseDir: './src', // Base directory for resolving imports (default: cwd)
onDuplicateDeclarations: 'error', // Handle duplicate type names: 'error' (default), 'warn', 'silent'
// Note: rootType is not supported (generates schemas for all types)
});includeJSDoc (optional)
- Type:
boolean - Default:
true - Description: Controls whether JSDoc comments are processed and included in the schema
When true (default):
- Interface/type descriptions are extracted from JSDoc comments
- Property descriptions are included
- JSDoc tags like
@minimum,@maximum,@patternare applied as constraints
When false:
- All JSDoc comments are ignored
- Schema only contains structural information (types, properties, required fields)
- Useful for generating minimal schemas or when descriptions aren't needed
Example:
const schema = toJsonSchema(`
/** User profile */
interface User {
/** @minLength 1 */
name: string;
}
`, { rootType: 'User', includeJSDoc: false });
// Result: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] }
// No description or minLength constraintincludeSchema (optional)
- Type:
boolean - Default:
true - Description: Controls whether the
$schemafield is included in generated schemas
When true (default):
- Each generated schema includes a
$schemafield pointing to the JSON Schema specification - Makes schemas self-contained and improves IDE validation support
- Uses the URL from
schemaVersionoption (default:https://json-schema.org/draft/2020-12/schema)
When false:
- The
$schemafield is omitted from all generated schemas - Useful when embedding schemas in larger documents or when the schema version is managed elsewhere
Example:
const schema = toJsonSchema(`
interface User {
name: string;
}
`, { rootType: 'User', includeSchema: true });
// Result includes: { "$schema": "https://json-schema.org/draft/2020-12/schema", type: 'object', ... }Batch generation: The toJsonSchemas() function also respects this option and includes $schema in each generated schema by default.
schemaVersion (optional)
- Type:
string - Default:
"https://json-schema.org/draft/2020-12/schema" - Description: Specifies the JSON Schema draft version URL
Use this to generate schemas compatible with different JSON Schema drafts:
// Generate draft-07 compatible schema
const schema = toJsonSchema(`interface User { name: string; }`, {
rootType: 'User',
schemaVersion: 'http://json-schema.org/draft-07/schema#'
});
// Result includes: { "$schema": "http://json-schema.org/draft-07/schema#", ... }Note: This library always generates draft-2020-12 compatible schemas. The schemaVersion option only changes the $schema field value. For maximum compatibility with draft-07 validators, use toJsonSchemas() which uses definitions instead of $defs.
additionalProperties (optional)
- Type:
boolean | undefined - Default:
undefined - Description: Sets the default value for
additionalPropertieson all object schemas
This option provides a global default for additionalProperties when not explicitly set via JSDoc or index signatures.
Precedence (highest to lowest):
- Index signature:
[key: string]: T→additionalProperties: T - JSDoc
@additionalPropertiestag strictObjectsoptionadditionalPropertiesoption- Not set (JSON Schema default behavior)
Example:
// Set all objects to disallow additional properties by default
const schema = toJsonSchema(`
interface User {
name: string;
}
`, { rootType: 'User', additionalProperties: false });
// Result: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'], additionalProperties: false }@additionalProperties JSDoc Tag
Control additionalProperties on specific types or properties using the @additionalProperties JSDoc tag.
Supported values: true | false (case-insensitive)
Usage at interface/type level:
/**
* Strict configuration object
* @additionalProperties false
*/
interface Config {
host: string;
port: number;
}
// Result: { type: 'object', properties: {...}, additionalProperties: false }Usage at property level:
interface Settings {
/**
* Database configuration
* @additionalProperties false
*/
database: {
host: string;
port: number;
};
}
// Result: database property has additionalProperties: falseInteraction with other options:
- When
includeJSDoc: false, the tag is ignored - The tag overrides the global
additionalPropertiesandstrictObjectsoptions - Index signatures take precedence over the tag
followImports (optional)
- Type:
"none" | "local" | "all" - Default:
"none"(programmatic API),"local"(CLI) - Description: Controls import resolution across multiple TypeScript files
Modes:
none: Single-file mode, imports are ignoredlocal: Follows relative imports (./and../), skipsnode_modulesall: Reserved for futurenode_modulessupport (currently behaves likelocal)
Only available with file-based APIs (toJsonSchemaFromFile(), toJsonSchemasFromFile(), and toJsonSchemasFromFiles()) — the string-based APIs (toJsonSchema() and toJsonSchemas()) do not support import resolution.
Example:
// Given: pet.ts exports Pet interface
// Given: api.ts imports Pet and uses it in PostPetReq
const schema = toJsonSchemaFromFile('./api.ts', {
followImports: 'local',
rootType: 'PostPetReq'
});
// Result: Schema includes both Pet (in $defs) and PostPetReqFeatures:
- Circular dependency detection (prevents infinite loops)
- Duplicate name handling (configurable with
onDuplicateDeclarationsoption) - Automatic extension resolution (
.ts,.tsx,.d.ts) - Index file resolution (
./types→./types/index.ts)
baseDir (optional)
- Type:
string - Default:
path.dirname(filePath) - Description: Base directory for resolving relative imports
Only relevant when followImports is not "none".
onDuplicateDeclarations (optional)
- Type:
"error" | "warn" | "silent" - Default:
"error" - Description: Controls how to handle duplicate type names across multiple files
Only relevant when followImports is not "none" (requires import resolution).
Modes:
error(default): Throws an error when the same type name is found in multiple fileswarn: Uses the first declaration encountered and logs a warning toconsole.warnsilent: Uses the first declaration encountered without any warning
When to use:
error: Strict mode for catching unintentional duplicates (recommended for most cases)warn: Development mode where you want to be notified but not block executionsilent: When you have intentional duplicates and want to use the first declaration
Example:
// File 1: schemas/CampaignImage.ts
export interface ImageDimensions {
width: number;
height: number;
format?: string;
}
// File 2: schemas/BrandAsset.ts
export interface ImageDimensions {
width: number;
height: number;
format: string; // Required (different from File 1)
}
// With error mode (default) - throws error
toJsonSchemaFromFile('entry.ts', {
followImports: 'local'
});
// Error: Duplicate declaration "ImageDimensions" found in:
// .../CampaignImage.ts
// .../BrandAsset.ts
// With warn mode - uses first declaration
toJsonSchemaFromFile('entry.ts', {
followImports: 'local',
onDuplicateDeclarations: 'warn'
});
// Warning: Duplicate declaration "ImageDimensions" found...
// Uses ImageDimensions from CampaignImage.ts (format is optional)
// With silent mode - uses first declaration without warning
toJsonSchemaFromFile('entry.ts', {
followImports: 'local',
onDuplicateDeclarations: 'silent'
});
// No warning, uses ImageDimensions from CampaignImage.tsBest practice: Keep the default error mode to catch duplicate names early. If you encounter duplicates:
- Check if the types are structurally identical — if so, extract to a shared file
- If they're different but have the same name, rename one of them for clarity
- Use
warnorsilentmode only as a temporary workaround
defineId (optional)
- Type:
(originalName: string, declaration: Declaration, context?: { absolutePath: string; relativePath: string }) => string - Default:
undefined - Description: Assigns a
$idto each schema and uses external$refinstead of local#/definitions/refs
When set on batch APIs (toJsonSchemas, toJsonSchemasFromFile, toJsonSchemasFromFiles):
- Each schema gets a
$idfield (the return value of the callback) - Internal
$refpointers become external refs pointing to the$idof the referenced type - The
definitionsblock is omitted entirely - The
$idis used as the key in the returnedRecord<string, JSONSchema>
This is designed for use with AJV's global registry, where schemas are registered by $id and cross-references are resolved at validation time.
Example with AJV:
import { toJsonSchemas } from "ts-source-to-json-schema";
import Ajv from "ajv";
const schemas = toJsonSchemas(`
interface User { id: string; name: string; }
interface Post { title: string; author: User; }
`, {
defineId: (name) => \`schemas.\${name}\`
});
// schemas = {
// "schemas.User": {
// "$id": "schemas.User",
// "$schema": "...",
// "type": "object",
// "properties": { "id": { "type": "string" }, "name": { "type": "string" } }
// },
// "schemas.Post": {
// "$id": "schemas.Post",
// "$schema": "...",
// "type": "object",
// "properties": { "title": { "type": "string" }, "author": { "$ref": "schemas.User" } }
// }
// }
// Register all schemas with AJV
const ajv = new Ajv();
for (const schema of Object.values(schemas)) {
ajv.addSchema(schema);
}
// Validate — AJV resolves $ref: "schemas.User" from its global registry
const validate = ajv.getSchema("schemas.Post");
validate({ title: "Hello", author: { id: "1", name: "Joel" } }); // ✅With file context for namespacing:
const schemas = toJsonSchemasFromFiles('src/schemas/**/*.ts', {
followImports: 'local',
defineId: (name, decl, ctx) => {
const dir = ctx?.relativePath.replace(/\.ts$/, '').replace(/\//g, '.') ?? '';
return dir ? \`\${dir}.\${name}\` : name;
}
});Can be combined with defineNameTransform — both options are independent. defineId controls $id/external $ref, while defineNameTransform controls $defs/#/definitions/ names.
Throws if the callback returns duplicate $id values for different types.
What it doesn't handle
Anything that requires the type checker to evaluate:
- Conditional types (
T extends U ? X : Y) - Mapped types (
{ [K in keyof T]: ... }) - Template literal types (
`${A}-${B}`) typeof,keyof,infernode_modulesimports (planned for future)
Generic type parameter limitations:
- Currently assumes conventional type parameter names (
T,U,V,W) - Custom parameter names like
interface Box<TValue> { value: TValue }won't work correctly (it would look forTinstead ofTValue) - This works for 95%+ of real-world cases where generics use standard names
- Maximum 4 type parameters supported
If you need these, use ts-json-schema-generator. If your types look like API contracts and tool definitions, this is probably all you need.
