Package Exports
- ts-json-schema-generator
Readme
ts-json-schema-generator
Extended version of https://github.com/xiag-ag/typescript-to-json-schema.
- Inspiration
- CLI Usage
tjsg autocomplete [SHELL]
tjsg generate [PATH]
tjsg help [COMMAND]
- Current state
- Contributors
- Programmatic Usage
- Run locally
- Publish
Inspiration
Inspired by YousefED/typescript-json-schema
. Here's the differences list:
- this implementation avoids the use of
typeChecker.getTypeAtLocation()
(so probably it keeps correct type aliases) - processing AST and formatting JSON schema have been split into two independent steps
- not exported types, interfaces, enums are not exposed in the
definitions
section in the JSON schema
CLI Usage
Run the schema generator with npx:
$ npx ts-json-schema-generator -t 'My.Type.Name' 'my/project/**/*.ts'
Or install the package and then run it
$ npm install -D ts-json-schema-generator
$ node_modules/.bin/ts-json-schema-generator -t 'My.Type.Name' 'my/project/**/*.ts'
Note that different platforms (e.g. Windows) may use different path separators so you may have to adjust the command above.
Also note that you need to quote paths with *
as otherwise the shell will expand the paths and therefore only pass the first path to the generator.
Options
tjsg autocomplete [SHELL]
Display autocomplete installation instructions.
USAGE
$ tjsg autocomplete [SHELL] [-r]
ARGUMENTS
SHELL (zsh|bash|powershell) Shell type
FLAGS
-r, --refresh-cache Refresh cache (ignores displaying instructions)
DESCRIPTION
Display autocomplete installation instructions.
EXAMPLES
$ tjsg autocomplete
$ tjsg autocomplete bash
$ tjsg autocomplete zsh
$ tjsg autocomplete powershell
$ tjsg autocomplete --refresh-cache
See code: @oclif/plugin-autocomplete
tjsg generate [PATH]
Generate JSON schema from your Typescript sources
USAGE
$ tjsg generate [PATH] [-t <value>] [--top-ref] [-i <value>] [-p <value>] [-e all|none|export] [-j
none|basic|extended] [--markdown-description] [--sort-props] [--strict-tuples] [--type-check] [--ref-encode]
[--additional-properties] [--functions fail|comment|hide] [--minify] [-o <value>] [--extra-tags <value>]
[--discriminator-type json-schema|open-api]
ARGUMENTS
PATH Source file path
FLAGS
-e, --expose=<option> [default: export] Type exposing
<options: all|none|export>
-i, --id=<value> $id for generated schema
-j, --jsdoc=<option> [default: extended] Read JsDoc annotations
<options: none|basic|extended>
-o, --out=<value> Set the output file (default: stdout)
-p, --tsconfig=<value> Your tsconfig.json to load entry files and compilation settings
-t, --type=<value> Type name
--additional-properties Allow additional properties for objects with no index signature
--discriminator-type=<option> [default: json-schema] Type of discriminator to use
<options: json-schema|open-api>
--extra-tags=<value>... [default: ] Provide additional validation keywords to include
--functions=<option> [default: comment] How to handle functions. `fail` will throw an error. `comment`
will add a comment. `hide` will treat the function like a NeverType or HiddenType.
<options: fail|comment|hide>
--markdown-description Generate `markdownDescription` in addition to `description`. Implies
--jsdoc=extended
--minify Minify generated schema
--[no-]ref-encode Encode references
--[no-]sort-props Makes the schema stable by sorting properties
--strict-tuples Do not allow additional items on tuples
--[no-]top-ref Create a top-level $ref definition
--[no-]type-check Type checks to improve performance
DESCRIPTION
Generate JSON schema from your Typescript sources
EXAMPLES
Analyzes src/types.ts using tsconfig.json and writes the schema to schema.json.
$ tjsg generate -f tsconfig.json -o schema.json src/types.ts
See code: src/commands/generate.ts
tjsg help [COMMAND]
Display help for tjsg.
USAGE
$ tjsg help [COMMAND...] [-n]
ARGUMENTS
COMMAND... Command to show help for.
FLAGS
-n, --nested-commands Include all nested commands in the output.
DESCRIPTION
Display help for tjsg.
See code: @oclif/plugin-help
Current state
interface
typesenum
typesunion
,tuple
,type[]
typesDate
,RegExp
,URL
typesstring
,boolean
,number
types"value"
,123
,true
,false
,null
,undefined
literals- type aliases
- generics
typeof
keyof
- conditional types
- functions
Promise<T>
unwraps toT
export *
to include all exported types
Contributors
This project is made possible by a community of contributors. We welcome contributions of any kind (issues, code, documentation, examples, tests,...). Please read our code of conduct.
Programmatic Usage
You can use the library programmatically as well:
import tsj, { type Config } from "ts-json-schema-generator";
import fs from "node:fs";
const config: Config = {
path: "path/to/source/file",
tsconfig: "path/to/tsconfig.json",
type: "*", // Or <type-name> if you want to generate schema for that one type only
};
const outputPath = "path/to/output/file";
const schema = tsj.createGenerator(config).createSchema(config.type);
const schemaString = JSON.stringify(schema, null, 2);
await fs.promises.writeFile(outputPath, schemaString, { encoding: "utf-8" });
Custom formatting
Extending the built-in formatting is possible by creating a custom formatter and adding it to the main formatter:
- First we create a formatter, in this case for formatting function types (note that there is a built in one):
import { BaseType, Definition, FunctionType, SubTypeFormatter } from "ts-json-schema-generator";
import ts from "typescript";
export class MyFunctionTypeFormatter implements SubTypeFormatter {
// You can skip this line if you don't need childTypeFormatter
public constructor(private childTypeFormatter: TypeFormatter) {}
public supportsType(type: BaseType): boolean {
return type instanceof FunctionType;
}
public getDefinition(type: FunctionType): Definition {
// Return a custom schema for the function property.
return {
type: "object",
properties: {
isFunction: {
type: "boolean",
const: true,
},
},
};
}
// If this type does NOT HAVE children, generally all you need is:
public getChildren(type: FunctionType): BaseType[] {
return [];
}
// However, if children ARE supported, you'll need something similar to
// this (see src/TypeFormatter/{Array,Definition,etc}.ts for some examples):
public getChildren(type: FunctionType): BaseType[] {
return this.childTypeFormatter.getChildren(type.getType());
}
}
- Then we add the formatter as a child to the core formatter using the augmentation callback:
import { createProgram, createParser, SchemaGenerator, createFormatter } from "ts-json-schema-generator";
import { MyFunctionTypeFormatter } from "./my-function-formatter.ts";
import fs from "fs";
const config = {
path: "path/to/source/file",
tsconfig: "path/to/tsconfig.json",
type: "*", // Or <type-name> if you want to generate schema for that one type only
};
// We configure the formatter an add our custom formatter to it.
const formatter = createFormatter(config, (fmt, circularReferenceTypeFormatter) => {
// If your formatter DOES NOT support children, e.g. getChildren() { return [] }:
fmt.addTypeFormatter(new MyFunctionTypeFormatter());
// If your formatter DOES support children, you'll need this reference too:
fmt.addTypeFormatter(new MyFunctionTypeFormatter(circularReferenceTypeFormatter));
});
const program = createProgram(config);
const parser = createParser(program, config);
const generator = new SchemaGenerator(program, parser, formatter, config);
const schema = generator.createSchema(config.type);
const schemaString = JSON.stringify(schema, null, 2);
await fs.promises.writeFile(outputPath, schemaString, { encoding: "utf-8" });
Custom parsing
Similar to custom formatting, extending the built-in parsing works practically the same way:
- First we create a parser, in this case for parsing construct types:
// my-constructor-parser.ts
import { Context, StringType, ReferenceType, BaseType, SubNodeParser } from "ts-json-schema-generator";
// use typescript exported by TJS to avoid version conflict
import ts from "ts-json-schema-generator";
export class MyConstructorParser implements SubNodeParser {
supportsNode(node: ts.Node): boolean {
return node.kind === ts.SyntaxKind.ConstructorType;
}
createType(node: ts.Node, context: Context, reference?: ReferenceType): BaseType | undefined {
return new StringType(); // Treat constructors as strings in this example
}
}
- Then we add the parser as a child to the core parser using the augmentation callback:
import { createProgram, createParser, SchemaGenerator, createFormatter, type Config } from "ts-json-schema-generator";
import { MyConstructorParser } from "./my-constructor-parser.ts";
import fs from "node:fs";
const config: Config = {
path: "path/to/source/file",
tsconfig: "path/to/tsconfig.json",
type: "*", // Or <type-name> if you want to generate schema for that one type only
};
const program = createProgram(config);
// We configure the parser an add our custom parser to it.
const parser = createParser(program, config, (prs) => {
prs.addNodeParser(new MyConstructorParser());
});
const formatter = createFormatter(config);
const generator = new SchemaGenerator(program, parser, formatter, config);
const schema = generator.createSchema(config.type);
const schemaString = JSON.stringify(schema, null, 2);
await fs.promises.writeFile(outputPath, schemaString, { encoding: "utf-8" });
Run locally
You can also run this tool locally:
- Clone the repository
$ git clone https://github.com/vega/ts-json-schema-generator.git
$ cd ts-json-schema-generator
- Install dependencies
$ yarn
- Run the tool
$ yarn --silent run run --path 'test/valid-data/type-mapped-array/*.ts' --type 'MyObject'
Or run with debugging:
$ yarn --silent run debug --path 'test/valid-data/type-mapped-array/*.ts' --type 'MyObject'
And connect via the debugger protocol.
AST Explorer is amazing for developers of this tool!
Publish
Publishing is handled by a 2-branch pre-release process, configured in publish-auto.yml
. All changes should be based off the default next
branch, and are published automatically.
- PRs made into the default branch are auto-deployed to the
next
pre-release tag on NPM. The result can be installed withnpm install ts-json-schema-generator@next
- When merging into
next
, please use thesquash and merge
strategy.
- When merging into
- To release a new stable version, open a PR from
next
intostable
using this compare link.- When merging from
next
intostable
, please use thecreate a merge commit
strategy.
- When merging from