Skip to content

NathanJAdams/json-schema-to-ts

Repository files navigation

json-schema-typescript-generator

Generate typescript files from json schema files

Contents

Install

Usage

Typescript

JSONSchema

Approach

Install

Install via one of the commands

npm -i json-schema-typescript-generator -D
yarn add json-schema-typescript-generator -D

Usage

To generate .ts files from the command line, run the command json-schema-typescript-generator.

Usage: json-schema-typescript-generator [options]

Option Description
-c, --cwd Working directory (default: process.cwd())
-s, --source Source directory of schema files, relative to working directory (default: src/schemas)
-d, --destination Destination directory of generated .ts files, relative to working directory (default: src/generated)
-e, --encoding Encoding of source files, one of: [ascii, utf8, utf-8, utf16le, ucs2, ucs-2, base64, base64url, latin1, binary, hex] (default: utf-8)
-r, --recursive Recurse into source directory and generate from nested files (default: true)
-R, --no-recursive Only generate from schema files directly in source directory, do not recurse deeper
-p, --pre-clean Delete destination directory before generating files (default: false)
-P, --no-pre-clean Overwrite destination directory when generating files
-i, --index-files Add index files (default: true)
-I, --no-index-files Do not add index files
-o, --optional-field-pattern The pattern to use for optional fields, one of: [QUESTION, PIPE_UNDEFINED] (default: QUESTION)
-u, --untyped-type The untyped field type, one of: [ANY, NEVER, UNDEFINED, UNKNOWN] (default: UNKNOWN)
-h, --help Display help for command

It is also possible to run the command within code by importing from the library. To generate .ts files, invoke the generateFiles function with an Options object like so

import { generateFiles, Options } from 'json-schema-typescript-generator';

const options: Options = {...}
await generateFiles(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;

Typescript

There are 2 options which define the style of code generated

OptionalFieldPattern

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;
};

UntypedType

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;
};

JSONSchema

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
$defs Combined with definitions
const null
booleans
numbers
strings
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
Map<K, V> - Map if items is a schema, uniqueItems=true, additionalItems=false and items has no other properties
Set<T> - Set if items is a schema, uniqueItems=true and is not a Map
[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 size
No 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

Approach

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

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •