Generate typescript files from json schema files
Install via one of the commands
npm -i json-schema-typescript-generator -D
yarn add json-schema-typescript-generator -D
To generate .ts files, invoke the main
function with an Options
object like so
import { main, Options } from 'json-schema-typescript-generator';
const options: Options = {...}
main(options);
The Options object is defined as follows:
{
files: {
cwd: string;
source: {
dir: string;
encoding: BufferEncoding;
recursive: boolean;
};
destination: {
dir: string;
preClean: boolean;
indexFiles: boolean;
};
};
ts: {
optionalFields: OptionalFieldPattern;
untyped: UntypedType;
};
}
All options are optional and fall back to their defaults if not given, which are as follows:
{
files: {
cwd: process.cwd(),
source: {
dir: 'src/schemas',
encoding: 'utf-8',
recursive: true
},
destination: {
dir: 'src/generated',
preClean: false,
indexFiles: true
}
},
ts: {
optionalFields: OptionalFieldPattern.QUESTION,
untyped: UntypedType.UNKNOWN
}
}
The option
options.files.destination.preClean
defines whether the destination folder will be deleted before generating typescript files.
The option
options.files.destination.indexFiles
defines whether index.ts files will be generated in each destination folder.
Note that the folders given by the options
options.files.source.dir
options.files.destination.dir
will be resolved relative to the folder given by the option
options.files.cwd
There are 2 options which define the style of code generated
The option
options.ts.optionalFields
defines how optional fields are represented and can take 1 of 2 values:
OptionalFieldPattern.QUESTION
type Example = {
a?: string;
};
or
OptionalFieldPattern.PIPE_UNDEFINED
type Example = {
a: string | undefined;
}
The option
options.ts.untyped
defines the fallback type used for types that failed to be generated, eg. perhaps the schema was empty, or an id was missing or a typo was made in a $ref entry etc. It can take 1 of 4 values:
UntypedType.ANY
type Example = {
a: any
}
or
UntypedType.NEVER
type Example = {
a: never
}
or
UntypedType.UNDEFINED
type Example = {
a: undefined
}
or
UntypedType.UNKNOWN
type Example = {
a: unknown
}
Support for properties defined in the JSON Schema are as follows:
Key | Support | Notes |
---|---|---|
$id | ✔ | |
$schema | ✘ | Action in TODO to support specific schema versions |
$ref | ✔ | local definition absolute reference to root/inner definition relative reference to root/inner definition |
enum | ✔ | null booleans numbers strings |
type | ✔ | "null" "boolean" "integer" "number" "string" "array" "object" Or an array of the above |
number properties | ✘ | multipleOf minimum maximum exclusiveMinimum exclusiveMaximum No typescript support for multipleOf Open question on GitHub about number ranges |
string properties | ✘ | minLength maxLength pattern format Typescript support for string patterns and formats in v4.1 Typescript's implementation produces a union of every possible combination so is not suitable for patterns or formats |
array properties | ✔ | items uniqueItems additionalItems T[] - Array if items is a schema and uniqueItems=false Set<T> - Set if items is a schema and uniqueItems=true [T, U, V] - Tuple if items is an array |
array properties | ✘ | contains minItems maxItems array (and possibly tuple) min length: type MinLengthArray<T> = [T, T, ...T[]]; Although no typescript support for a Set<T> of specific sizeNo typescript support for contains |
object properties | ✔ | properties additionalProperties |
combinations | ✔ | allOf anyOf oneOf If oneOf is used, OneOf_n types are dynamically generated in files that need them, for arrays with many items these types can get large and will be updated if typescript adds native support |
The approach this package takes is to only do one thing but do it well, ie. transforming schema files to typescript files. It doesn't download any schemas, or do any validation, consistency checking, linting, prettifying etc. It assumes the schema author knows exactly what they want and it will generate typescript files that represent the schemas given as closely as possible, even if the generated types don't make sense or cannot be satisfied.
An example will make this clear:
Given the following schema in a file called A.json
{
"type": "number",
"$ref": "#/definitions/BOOL",
"enum": [
null,
"tuv",
"xyz"
],
"definitions": {
"BOOL": {
"type": "boolean"
}
}
}
Invoking the generator will generate a file A.ts
containing:
export type A = BOOL
& (null | 'tuv' | 'xyz')
& number;
export type BOOL = boolean;
Clearly type A
cannot ever be satisfied, but it does match what the schema specified