Giter Site home page Giter Site logo

ts-json-schema-generator's Introduction

ts-json-schema-generator

Test codecov npm version

Extended version of https://github.com/xiag-ag/typescript-to-json-schema.

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

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.

CLI Usage

Run the schema generator with npx:

npx ts-json-schema-generator --path 'my/project/**/*.ts' --type 'My.Type.Name'

Or install the package and then run it

npm install --save ts-json-schema-generator
./node_modules/.bin/ts-json-schema-generator --path 'my/project/**/*.ts' --type 'My.Type.Name'

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

  -p, --path <path>              Source file path
  -t, --type <name>              Type name
  -i, --id <name>                $id for generated schema
  -f, --tsconfig <path>          Custom tsconfig.json path
  -e, --expose <expose>          Type exposing (choices: "all", "none", "export", default: "export")
  -j, --jsDoc <extended>         Read JsDoc annotations (choices: "none", "basic", "extended", default: "extended")
  --markdown-description         Generate `markdownDescription` in addition to `description`.
  --functions <functions>        How to handle functions. `fail` will throw an error. `comment` will add a comment. `hide` will treat the function like a NeverType or HiddenType.
                                 (choices: "fail", "comment", "hide", default: "comment")
  --minify                       Minify generated schema (default: false)
  --unstable                     Do not sort properties
  --strict-tuples                Do not allow additional items on tuples
  --no-top-ref                   Do not create a top-level $ref definition
  --no-type-check                Skip type checks to improve performance
  --no-ref-encode                Do not encode references
  -o, --out <file>               Set the output file (default: stdout)
  --validation-keywords [value]  Provide additional validation keywords to include (default: [])
  --additional-properties        Allow additional properties for objects with no index signature (default: false)
  -V, --version                  output the version number
  -h, --help                     display help for command

Programmatic Usage

// main.js

const tsj = require("ts-json-schema-generator");
const fs = require("fs");

/** @type {import('ts-json-schema-generator/dist/src/Config').Config} */
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
};

const outputPath = "path/to/output/file";

const schema = tsj.createGenerator(config).createSchema(config.type);
const schemaString = JSON.stringify(schema, null, 2);
fs.writeFile(outputPath, schemaString, (err) => {
    if (err) throw err;
});

Run the schema generator via node main.js.

Custom formatting

Extending the built-in formatting is possible by creating a custom formatter and adding it to the main formatter:

  1. First we create a formatter, in this case for formatting function types (note that there is a built in one):
// my-function-formatter.ts
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());
    }
}
  1. 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 outputPath = "path/to/output/file";

const schemaString = JSON.stringify(schema, null, 2);
fs.writeFile(outputPath, schemaString, (err) => {
    if (err) throw err;
});

Custom parsing

Similar to custom formatting, extending the built-in parsing works practically the same way:

  1. 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
    }
}
  1. Then we add the parser as a child to the core parser using the augmentation callback:
import { createProgram, createParser, SchemaGenerator, createFormatter } from "ts-json-schema-generator";
import { MyConstructorParser } from "./my-constructor-parser.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
};

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 outputPath = "path/to/output/file";

const schemaString = JSON.stringify(schema, null, 2);
fs.writeFile(outputPath, schemaString, (err) => {
    if (err) throw err;
});

Current state

  • interface types
  • enum types
  • union, tuple, type[] types
  • Date, RegExp, URL types
  • string, boolean, number types
  • "value", 123, true, false, null, undefined literals
  • type aliases
  • generics
  • typeof
  • keyof
  • conditional types
  • functions

Run locally

yarn --silent run run --path 'test/valid-data/type-mapped-array/*.ts' --type 'MyObject'

Debug

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 with npm install ts-json-schema-generator@next
    • When merging into next, please use the squash and merge strategy.
  • To release a new stable version, open a PR from next into stable using this compare link.
    • When merging from next into stable, please use the create a merge commit strategy.

ts-json-schema-generator's People

Contributors

alexts0 avatar andreashuber69 avatar andrewleedham avatar arthurfiorette avatar bywo avatar daanboer avatar dependabot-preview[bot] avatar dependabot[bot] avatar domoritz avatar filipomar avatar flugg avatar fwal avatar greenkeeper[bot] avatar hmil avatar hydrosquall avatar jason3s avatar jirutka avatar joshkel avatar kayahr avatar loopingz avatar marcoqu avatar mrix avatar paulmelnikow avatar robertdempsey avatar semantic-release-bot avatar simonlovesyou avatar sramam avatar stevenlandis-rl avatar thejuan avatar vfernandestoptal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ts-json-schema-generator's Issues

Future of JSON schema for Vega and Vega-Lite

This is a discussion. Please add your comments below.

I keep running into a wall when trying to use JSON schema with intersection types. I’d like to use anyOf but in combination with additionalProperties: false we end up with a schema that cannot be satisfied unless you only use properties that are defined in the intersection of the properties. So far, we have generated huge objects that merge properties but this is causing problems with intersections with unions (e.g. A & (B | C)). Going forward, I’d like to address this properly and see three options. 1) abandon JSON schema and use a more sophisticated schema enforcement 2) abandon additionalProperties: false, which means users won’t know if the mistype properties (this is what Vega does in some places), or 3) translate A & (B | C) to (A & B) | (A & C) and generate an anyOf of multiple large objects that are possibly largely the same. In the worse case, this can get exponentially larger. For example (A | B) & (C | D) = A & C | A & D | B & C | B & D Opinions?

See related issues: #62 and #4.

Another issue with JSON schema is inheritance, which cannot be expressed. So far we keep creating large objects for this case as well.

Create programmatic use examples

Looking for a more up to date ts-json-schema generator since I've got a ton of errors from https://github.com/YousefED/typescript-json-schema most likely due to the TS version (though I'm not sure).

Would love to try this out, but need some examples for programmatic use to get started.

I'm building an API/client and using json schema to compare results from API with my TS interfaces during unit tests :)

Thanks!

Nicer schema for string literals + string

I believe this only requires minor changes in https://github.com/vega/ts-json-schema-generator/blob/master/src/TypeFormatter/EnumTypeFormatter.ts.

export interface MyObject {
    bar: "ok" | "fail" | "abort" | string;
}

produces

> [email protected] run /Users/domoritz/Developer/UW/ts-json-schema-generator
> ts-node ts-json-schema-generator.ts "--path" "test.ts" "--type" "MyObject"

{
  "$ref": "#/definitions/MyObject",
  "$schema": "http://json-schema.org/draft-04/schema#",
  "definitions": {
    "MyObject": {
      "additionalProperties": false,
      "properties": {
        "bar": {
          "anyOf": [
            {
              "enum": [
                "ok"
              ],
              "type": "string"
            },
            {
              "enum": [
                "fail"
              ],
              "type": "string"
            },
            {
              "enum": [
                "abort"
              ],
              "type": "string"
            },
            {
              "type": "string"
            }
          ]
        }
      },
      "required": [
        "bar"
      ],
      "type": "object"
    }
  }
}

The enums could be consolidated.

"allOf" + "additionalProperties false" with interface extensions

export interface A {a: string;}
export interface B extends A {b?: string;}

generates

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "definitions": {
    "B": {
      "allOf": [
        {
          "type": "object",
          "properties": {
            "b": {
              "type": "string"
            }
          },
          "required": [],
          "additionalProperties": false
        },
        {
          "$ref": "#/definitions/A"
        }
      ]
    },
    "A": {
      "type": "object",
      "properties": {
        "a": {
          "type": "string"
        }
      },
      "required": [
        "a"
      ],
      "additionalProperties": false
    }
  },
  "$ref": "#/definitions/B"
}

The following object type checks correctly with TypeScript. However, it does not validate against the JSON schema. This is because B uses an allOf where each branch has additionalProperties: false (i.e., it fails the first branch).

const foobar:B = {a: 'foo'};

I believe ts2json should be consolidating these definitions together. Note: Switching allOf to anyOf doesn't yield a correct schema either ({b: 'foo'} correctly validates for instance).

Improve performance

The schema generator is super slow but it's not clear why. It takes more than a minute for Vega-Lite.

Better typings for tuples

We should support things like

export type A = [number, number]

and maybe

export type A = [number, number, number?]

Maximum call stack size exceeded

When I try to run typescript-to-json-schema against the Legend union type defined here, I get a Maximum call stack size exceeded error. Each individual type within the union builds just fine, however.

Is there something about my type definitions I should be modifying/simplifying, or is this a bug with typescript-to-json-schema?

$ ./node_modules/.bin/typescript-to-json-schema --path typings/legend.ts --type Legend
/Users/arvind/Research/vega3/vega-parser/node_modules/typescript-to-json-schema/dist/typescript-to-json-schema.js:32
        throw error;
        ^

RangeError: Maximum call stack size exceeded
    at CircularReferenceTypeFormatter.getChildren (/Users/arvind/Research/vega3/vega-parser/node_modules/typescript-to-json-schema/dist/src/CircularReferenceTypeFormatter.js:26:23)
...
$ ./node_modules/.bin/typescript-to-json-schema --path typings/legend.ts --type SizeLegend
(executes correctly)

Add support for conditional type nodes

Because of YousefED/typescript-json-schema#173 I'm currently trying to migrate to ts-json-schema-generator. The first problem I have with the new tool is missing support for conditional type nodes which worked fine with the typescript-json-schema tool. Here is a minimal example:

export type TypeName<T> =
    T extends string ? "string" :
    T extends number ? "number" :
    T extends boolean ? "boolean" :
    "object";

export type TestJSON = TypeName<string>;

When I try to generate the schema for TestJSON with this tool then I get this error message:

UnknownNodeError: Unknown node "TypeName<string>" (ts.SyntaxKind = 176)

I really like the clean structure of the new tool and it looks pretty straight forward how to implement this feature by adding a ConditionalTypeNodeParser class like this:

export class ConditionalTypeNodeParser implements SubNodeParser {
    public constructor(
        private typeChecker: ts.TypeChecker,
        private childNodeParser: NodeParser,
    ) {
    }

    public supportsNode(node: ts. ConditionalTypeNode): boolean {
        return node.kind === ts.SyntaxKind.ConditionalType;
    }

    public createType(node: ts.ConditionalTypeNode, context: Context): BaseType {
        ... magic here ...
    }
}

But unfortunately I lack the skills to implement the createType method. In theory the method has to check if node.checkType is assignable to node.extendsType and then returns node.trueType or node.falseType. But I don't know if this assignability check must be written from scratch here or if TypeScript already exposes some functionality to do this. And it gets more complicated if the check type is a union type so TypeName<string | Date> is resolved to "string" | "object" in this example.

An in-range update of @types/node is breaking the build 🚨

The devDependency @types/node was updated from 11.10.4 to 11.10.5.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/node is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Strange errors on generation

Users/sanjay/Workspace/Repos/bridge-client/node_modules/types/node/index.d.ts(609,10): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
Users/sanjay/Workspace/Repos/bridge-client/node_modules/@types/node/index.d.ts(815,38): error TS2583: Cannot find name 'Set'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
Users/sanjay/Workspace/Repos/bridge-client/node_modules/@types/node/index.d.ts(2641,10): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
Users/sanjay/Workspace/Repos/bridge-client/node_modules/@types/node/index.d.ts(6428,14): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
Users/sanjay/Workspace/Repos/bridge-client/node_modules/@types/ws/index.d.ts(191,18): error TS2583: Cannot find name 'Set'. Do you need to change your target library? Try changing the `lib` compiler option to es2015 or later.
Users/sanjay/Workspace/Repos/bridge-client/node_modules/typescript/lib/lib.dom.d.ts(8546,11): error TS2300: Duplicate identifier 'Headers'.
Users/sanjay/Workspace/Repos/bridge-client/node_modules/typescript/lib/lib.dom.d.ts(8555,13): error TS2300: Duplicate identifier 'Headers'.
Users/sanjay/Workspace/Repos/bridge-client/src/generated/types.d.ts(3,6): error TS2300: Duplicate identifier 'Headers'.

I get these errors when trying to generate schema from a typings file. For reference:

  • I have a type Headers defined in my typings file.
  • I use Symbols as type parameters (e.g. type Id<T> = string and type UserId = Id<'User'>).
  • I never use the type Set in my typings file.
  • My tsconfig.json uses ES2018.

Any ideas how to fix this? Thanks!

Ability to extend Array in circular reference

Hi! I 'm having some trouble with generating JSON schema for types with circular references. I would like to generate the schema for the following:

export type Tag = TagPrimitive | Tag[];
export type TagPrimitive = string | number | boolean | null;

However, as this isn't valid TypeScript, it is common to change it to the following:

export type Tag = TagPrimitive | TagArray;
export type TagPrimitive = string | number | boolean | null;
export interface TagArray extends Array<Tag> {}

This however results in the following error: Cannot read property 'getId' of undefined. So, the first version does generate the proper JSON schema, while the second is valid typescript. Is it possible to support the second method as well?

Name collision can override definition

As suspected, we have name collision issue here.

test1.ts

import { RealA } from "./test2";

export interface Parent {
  a: A;
}
export type A = RealA;

test2.ts

export interface RealA {
  a: A;
}
export type A = string;
./node_modules/.bin/ts-json-schema-generator \
    --path 'test.ts' \
    --type 'Parent' \
    --expose 'export' \
    --jsDoc 'extended'

Output: (A in test1.ts is gone!)

{
  "$ref": "#/definitions/Parent",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "A": {
      "type": "string"
    },
    "Parent": {
      "additionalProperties": false,
      "properties": {
        "a": {
          "$ref": "#/definitions/A"
        }
      },
      "required": [
        "a"
      ],
      "type": "object"
    },
    "RealA": {
      "additionalProperties": false,
      "properties": {
        "a": {
          "$ref": "#/definitions/A"
        }
      },
      "required": [
        "a"
      ],
      "type": "object"
    }
  }
}

An in-range update of ts-node is breaking the build 🚨

The devDependency ts-node was updated from 8.0.2 to 8.0.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

ts-node is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details

Release Notes for Relative TypeScript

Added

  • Fall back on resolving relative TypeScript packages (normal resolution is from working directory, these two things can be the same in the case of locally installed packages)
Commits

The new version differs by 10 commits.

  • 8706c31 8.0.3
  • d065dd2 Update README note about relative installations
  • 655c43b Fallback on resolving TypeScript relatively (#793)
  • c2ecc7d Add note about local TypeScript to README (#789)
  • 7414752 Update README with triple-slash directive example (#776)
  • efaf67a Add VS Code env note to README (#738)
  • 2609663 Avoid incrementing memory cache unnecessarily
  • b4bdb08 Specify sensitive file names for document registry
  • c215693 Utilize TypeScript sys better for service host
  • 062254f Conditionally enable .[tj]sx extensions

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

How to use existing tsconfig?

Just gave the project ago, but I'm seeing lots of errors like these:

/myproject/node_modules/@types/node/index.d.ts(390,48): error TS2304: Cannot find name 'Promise'.
/myproject/node_modules/@types/node/index.d.ts(392,62): error TS2304: Cannot find name 'Promise'.
/myproject/node_modules/@types/node/index.d.ts(505,50): error TS2304: Cannot find name 'Promise'.
/myproject/node_modules/@types/node/index.d.ts(507,65): error TS2304: Cannot find name 'Promise'.

Is there a way to override the included typescript libsdefinitions, or even better reuse the existing tsconfig.json?

Get json schema of parameters from a function

Would it be possible to get the JSON schema for the parameters of a function (or a method)?

For example:

export interface GetListInput {
    foo: string;
}

export function getList(input: GetListInput, input2: string) {
    // some code
}

I would get something like array:

{
  "$ref": "#/definitions/params",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "GetListInput": {
      "additionalProperties": false,
      "properties": {
        "foo": {
          "type": "string"
        }
      },
      "required": [
        "foo"
      ],
      "type": "object"
    },
    "params": {
      "items": [
        {
          "$ref": "#/definitions/GetListInput"
        },
        {
          "type": "string"
        }
      ],
      "maxItems": 2,
      "minItems": 2,
      "type": "array"
    }
  }

A & (B | C) would produce only A in the schema

From vega/vega-lite#4440 (comment):

export type TopLevelFacetedUnitSpec = TopLevel<FacetedExtendedUnitSpec> & DataMixins;`

TopLevel<S extends BaseSpec> = S &
  TopLevelProperties & {
...
}

export type FacetedExtendedUnitSpec = ExtendedUnitSpec<FacetMapping<Field>>;

export type ExtendedUnitSpec<
  /** Extra Encoding */
  EE = EmptyObject
> = NormalizedUnitSpec<EE> | CompositeUnitSpec<EE>;

Don't output intermediate aliases

export interface Parent {
  a: A;
}
export type A = RealA;

export type RealA = { realA: string };
./node_modules/.bin/ts-json-schema-generator \
    --path 'test.ts' \
    --type 'Parent' \
    --expose 'export' \
    --jsDoc 'extended'

outputs

{
  "$ref": "#/definitions/Parent",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "A": {
      "$ref": "#/definitions/RealA"
    },
    "Parent": {
      "additionalProperties": false,
      "properties": {
        "a": {
          "$ref": "#/definitions/A"
        }
      },
      "required": [
        "a"
      ],
      "type": "object"
    },
    "RealA": {
      "additionalProperties": false,
      "properties": {
        "realA": {
          "type": "string"
        }
      },
      "required": [
        "realA"
      ],
      "type": "object"
    }
  }
}

However, if RealA is not referred elsewhere, it's better to output:

{
  "$ref": "#/definitions/Parent",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "A": {
      "additionalProperties": false,
      "properties": {
        "realA": {
          "type": "string"
        }
      },
      "required": [
        "realA"
      ],
      "type": "object"
    },
    "Parent": {
      "additionalProperties": false,
      "properties": {
        "a": {
          "$ref": "#/definitions/A"
        }
      },
      "required": [
        "a"
      ],
      "type": "object"
    }
    
  }
}

`typeof {value}` throws when generating schema

Hey guys.

I'm trying to use a constant value as string literal types for an interface such as the following. Although it throws with the following output Cannot read property 'type' of undefined.

const FOO = 'foo';

interface Bar {
  value: typeof FOO;
};

I was wondering if you'd knew what might cause that. Or am I trying to use something that isn't supported by this library? Thanks!

ReferenceType has undefined type

I get the an undefined error trying to parse MyType.

import { View, ViewStyle, StyleProp } from 'react-native';
export type MyType = StyleProp<ViewStyle>
TypeError: Cannot read property 'getId' of undefined
    at ReferenceType.getId (/Users/awinograd/programming/ts-json-schema-generator/dist/src/Type/ReferenceType.js:12:26)                                                                                    
    at (.types.map (/Users/awinograd/programming/ts-json-schema-generator/dist/src/Type/UnionType.js:11:25)                                                                                                
    at Array.map (<anonymous>)
    at UnionType.getId (/Users/awinograd/programming/ts-json-schema-generator/dist/src/Type/UnionType.js:10:33)                                                                                            
    at ids.join.<.context.getArguments.map (/Users/awinograd/programming/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:33:78)                                                           
    at Array.map (<anonymous>)
    at CircularReferenceNodeParser.createCacheKey (/Users/awinograd/programming/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:33:61)                                                    
    at CircularReferenceNodeParser.createType (/Users/awinograd/programming/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:13:26)                                                        
    at ChainNodeParser.createType (/Users/awinograd/programming/ts-json-schema-generator/dist/src/ChainNodeParser.js:17:50)                                                                                
    at ExpressionWithTypeArgumentsNodeParser.createType (/Users/awinograd/programming/ts-json-schema-generator/dist/src/NodeParser/ExpressionWithTypeArgumentsNodeParser.js:23:41) 

So far, I've figured out that getId is called in createType before the returned value is actually set on the reference on the same line in CircularReferenceNodeParser

reference.setType(this.childNodeParser.createType(node, context));

Intent of extended JsDoc mode

I'd like to better understand the intent of the three JsDoc modes: none/Basic/Extended.

Atleast for my purpose, I'd like them to behave like so:

  • none: do not use JsDoc annotations (only use what the type system gives you?)
  • basic: only use spec compliant annotations
  • extended: allow non-standard annotations

But it seems this is not how things work.

Support Pick and other Mapped Types

Hi! Great library here. We are heavily experimenting with using json schemas generated from our TypeScript interfaces on both front end and back end and this is obviously the glue that's holding it all together! With that said, there are some scenarios we are encountering that we are having to work around to get our schemas generated the way we want to, the main issues being around Mapped Types.

Consider the following interfaces:

export interface ISortableProperties {
    /**
     * @description id
     */
    id: number;

    /**
     * @description name
     */
    name: string;

    /**
     * @description date
     */
    date: Date;
}

export interface IResponse {
    unsortableProperty: string;
}

export interface IRequest {
    sortBy: Sortify<Pick<ISortableProperties, "id">> | Sortify<Pick<ISortableProperties, "name">> | Sortify<Pick<ISortableProperties, "date">>
}

export type Sortify<T> = {
    [P in keyof T]: sorting.SortDirection
}

The schema I'd like to see from this is

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "additionalProperties": false,
  "definitions": {
    "sorting.SortDirection": {
      "enum": [
        "ASC",
        "DESC"
      ],
      "type": "string"
    }
  },
  "properties": {
    "sortBy": {
      "anyOf": [
        {
          "additionalProperties": false,
          "properties": {
            "id": {
              "$ref": "#/definitions/sorting.SortDirection",
              "description": "id"
            }
          },
          "required": [
            "id"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "properties": {
            "name": {
              "$ref": "#/definitions/sorting.SortDirection",
              "description": "name"              
            }
          },
          "required": [
            "name"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "properties": {
            "date": {
              "$ref": "#/definitions/sorting.SortDirection",
              "description": "date"              
            }
          },
          "required": [
            "date"
          ],
          "type": "object"
        }
      ]
    }
  },
  "required": [
    "sortBy"
  ],
  "type": "object"
}

But I actually get the error :
ts-json-schema-generator\dist\ts-json-schema-generator.js:30
throw error;
^

TypeError: Cannot read property 'reduce' of undefined.

Is there any possibility of supporting this kind of scenario?

Thanks!
Rob

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Union types and type intersections don't work together

Hello,

I am investigating whether we could use this library to generate json schemas from our existing TypeScript interfaces. I have run into an issue with union types and type intersections. Is this a known limitation? In the provided example the "c" field is not present at all in the output.

input (test.ts):

interface A {
  x: boolean;
  c: 'b';
}
interface B {
  x: boolean;
  c: 'c';
}
export type D = (A|B) & {x: true};

ts-json-schema-generator --strictTuples --path 'test.ts' --expose 'export' --type D

output:

{
  "$ref": "#/definitions/D",
  "$schema": "http://json-schema.org/draft-06/schema#",
  "definitions": {
    "D": {
      "additionalProperties": false,
      "properties": {
        "x": {
          "enum": [
            true
          ],
          "type": "boolean"
        }
      },
      "required": [
        "x"
      ],
      "type": "object"
    }
  }
}

Thanks,
Kálmán

setting additionalProperties to true

Not sure if this belongs in the vega fork or the original repo.
Looking at the code, it's not clear that 'additionalProperties' can ever be set to true in the generated schema.

Best I could figure was this function https://github.com/vega/typescript-to-json-schema/blob/master/src/NodeParser/InterfaceNodeParser.ts#L65 and it'll always return false.

There seem to be no test cases to the counter.

Would appreciate clarification and/or some idea of how to go about fixing this. Happy to submit a PR once given a scent to follow.

Support for `unknown` keyword

We are starting to use unknown instead of any in some of our types.
Do you think it makes sense to add support for it? Should it be treated the same as any?
Should the any-related classes be updated to also recognize the unknown keyword or should it have new separate implementation classes?

Thanks

Incorrect output for Generic with UnionType

export type Condition<T> = {
  selection: LogicalOperand<string>;
} & T;

Condition<FieldDef|ValueDef> only has property selection but no properties from FieldDef and ValueDef.

See vega/vega-lite@06cc8dc in vega/vega-lite#1980.

Note that this is no longer a blocking issue since I redeclare this using Condition<FieldDef> | Condition<ValueDef> which is a better declaration anyway.

(I'm just filing the bug here so we are aware of this bug.)

Cannot find name AsyncIterator/Iterable

Trying to use this on a simple file: environment.token.ts:

export interface EnvConfig {
  production: boolean;
  apiEndpoint: string;
}

Getting an error when running:

$ ts-json-schema-generator --path src/app/core/environment.token.ts --type EnvConfig
/Sites/mysite/node_modules/@types/graphql/subscription/subscribe.d.ts(17,12): error TS2304: Cannot find name 'AsyncIterator'.
/Sites/mysite/node_modules/@types/graphql/subscription/subscribe.d.ts(29,12): error TS2304: Cannot find name 'AsyncIterable'.

My tsconfig.json looks like the following (from an Angular CLI project):

{
  "compileOnSave": false,
  "compilerOptions": {
    "paths": {
      "app/*": ["./app/*"]
    },
    "baseUrl": "./src",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "es2015",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "alwaysStrict": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "target": "es5",
    "lib": [
      "es2017",
      "dom",
      "esnext.asynciterable"
    ],
    "plugins": [{
      "name": "@angular/language-service"
    }]
  }
}

It seems to be reading the whole project despite only giving it a single file

SchemaGenerator optimization

Hi, I'm working with a large TS codebase and I'm looking to optimize schema generation on file changes. So far, I've gotten SchemaGenerator hooked up to Typescript's incremental program watcher so ts.Program regenerations take ~20ms on file change.

Now, the bottleneck is SchemaGenerator.findRootNode(), which loops through every parsed file (including node_modules) looking for the type definition that matches the type name (taking about 600ms for us). I think we can speed this up by allowing the consumer to hint to SchemaGenerator which files to inspect first.

For example, if we know all of our exported types live in the ./types directory, we could tell SchemaGenerator to prioritize looking at files in the ./types directory. If the types we're looking to find don't exist, then continue looking at the rest of the files in the Program.

A few ideas:

  • SchemaGenerator could take a fileComparator: (fileA: ts.SourceFIle, fileB: ts.SourceFile) => number function argument in its constructor that sorts the source files on init.
  • SchemaGenerator could take a heuristic: (typeName: string, file: ts.SourceFile) => number function argument that scores files on whether the consumer thinks the type will exist there. SchemaGenerator would then look at high-scoring files first.

What do you think? If you like direction, I'm happy to open a PR

tuple validation

Hi,
when generating a schema for a tuple-like structure, I noticed some issues:

type Test = [number, number]

generates a schema that allows for additional values, while it shouldn't.

{
    "$schema": "http://json-schema.org/draft-06/schema#",
    "definitions": {
        "Test": {
            "type": "array",
            "items": [
                {
                    "type": "number"
                },
                {
                    "type": "number"
                }
            ],
            "minItems": 2,
            "additionalItems": {
                "anyOf": [
                    {
                        "type": "number"
                    },
                    {
                        "type": "number"
                    }
                ]
            }
        }
    },
    "$ref": "#/definitions/Test"
}

also,

type Test = [number, number, number|undefined]

requires at least three values, while it should require at least 2 and at most three.

Anyways, great project.

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Support Exclude

Error:

UnknownNodeError: Unknown node "Exclude<ParameterType, ParameterType.Enum | ParameterType.Number>" (ts.SyntaxKind = 175)

Code:

enum ParameterType {
    Enum = "enum",
    Number = "number",
    String = "string",
    Date = "date"
    //...
}

interface IParameter {
    type: Exclude<ParameterType, ParameterType.Enum | ParameterType.Number>;
}

"TypeError: Cannot read property 'reduce' of undefined" in MappedTypeNodeParser.getProperties

I am scratching my head about this crash for more then a few minutes now. Unfortunately I have no idea how to resolve this, but I have at least a source file that triggers the problem. The crash seems to be related to a rather complicated type I have:

// Resolves a value at runtime. The value must be the name of a parameter
// that has been formally introduced before.
export interface ParameterReference {
  "$ref": string
}

// Allows properties of an object to be optional and to be
// a reference that can be resolved to an actual value later.
export type ParameterReferenceable<T> = {
  [P in keyof T]?: T[P] | ParameterReference;
}

// Type can be generated without problems
export interface TestInterface {
  myStr: string;
  myNum: number;
}

// Crashes with stacktrace below
export type RefTestInterface = ParameterReferenceable<TestInterface>;

I attempted to generate the schemas as follows, the second call ends in the mentioned stacktrace.

./node_modules/.bin/ts-json-schema-generator --path ./repro.ts --type TestInterface
./node_modules/.bin/ts-json-schema-generator --path ./repro.ts --type RefTestInterface

The exact stacktrace reads like this and seems to be in the function MappedTypeNodeParser.getProperties:

TypeError: Cannot read property 'reduce' of undefined
    at MappedTypeNodeParser.getProperties (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/NodeParser/MappedTypeNodeParser.js:19:14)
    at MappedTypeNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/NodeParser/MappedTypeNodeParser.js:14:92)
    at ChainNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:17:50)
    at TypeAliasNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeAliasNodeParser.js:20:94)
    at AnnotatedNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/NodeParser/AnnotatedNodeParser.js:15:47)
    at ExposeNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/ExposeNodeParser.js:14:45)
    at CircularReferenceNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/CircularReferenceNodeParser.js:19:48)
    at ChainNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:17:50)
    at TypeReferenceNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/NodeParser/TypeReferenceNodeParser.js:22:41)
    at ChainNodeParser.createType (/home/marcus/projects/scratch-sql/schema/json/node_modules/ts-json-schema-generator/dist/src/ChainNodeParser.js:17:50)

My versions:

> node --version                                                                                                                                                      
v10.7.0
> grep "ts-json-schema-generator" package-lock.json                                                                                                                    
      "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-0.29.0.tgz",

An in-range update of @types/jest is breaking the build 🚨

The devDependency @types/jest was updated from 24.0.1 to 24.0.2.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/jest is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.