Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

json-schema-to-ts

Package Overview
Dependencies
Maintainers
1
Versions
81
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-schema-to-ts - npm Package Compare versions

Comparing version 1.5.0 to 1.6.0

lib/meta-types/exclusion/any.d.ts

2

lib/meta-types/enum.d.ts

@@ -0,1 +1,2 @@

import { A, B } from "ts-toolbelt";
import { Get } from "../utils";

@@ -9,1 +10,2 @@ export declare type EnumType = "enum";

export declare type ResolveEnum<T> = Values<T>;
export declare type IsEnumRepresentable<E> = A.Equals<Values<E>, never> extends B.True ? false : true;

12

lib/meta-types/intersection/enum.d.ts

@@ -12,7 +12,7 @@ import { Get } from "../../utils";

const: IntersectConst<B, A>;
enum: FilterExtendingResolved<A, B>;
primitive: FilterExtendingResolved<A, B>;
array: FilterExtendingResolved<A, B>;
tuple: FilterExtendingResolved<A, B>;
object: FilterExtendingResolved<A, B>;
enum: FilterUnintersecting<A, B>;
primitive: FilterUnintersecting<A, B>;
array: FilterUnintersecting<A, B>;
tuple: FilterUnintersecting<A, B>;
object: FilterUnintersecting<A, B>;
union: IntersectUnion<B, A>;

@@ -24,4 +24,4 @@ exclusion: IntersectExclusion<B, A>;

}[Get<B, "type"> extends MetaType ? Get<B, "type"> : "errorTypeProperty"];
declare type FilterExtendingResolved<A, B> = Enum<RecurseOnEnumValues<Values<A>, B>>;
declare type FilterUnintersecting<A, B> = Enum<RecurseOnEnumValues<Values<A>, B>>;
declare type RecurseOnEnumValues<V, B> = V extends infer T ? Intersect<Const<T>, B> extends Never ? never : T : never;
export {};
import { DoesExtend, Get } from "../../utils";
import { Resolve, MetaType, Never, Error } from "..";
import { ErrorType } from "../error";
import { IntersectConst } from "./const";

@@ -11,2 +12,3 @@ import { IntersectEnum } from "./enum";

import { ClearExclusionIntersections, IntersectExclusion } from "./exclusion";
import { IsRepresentable } from "../utils";
export declare type IntersectionType = "intersection";

@@ -39,3 +41,3 @@ export declare type Intersection<L, R> = {

any: B;
never: Never;
never: Get<B, "type"> extends ErrorType ? B : Never;
const: IntersectConst<A, B>;

@@ -53,1 +55,2 @@ enum: IntersectEnum<A, B>;

}[Get<A, "type"> extends MetaType ? Get<A, "type"> : "errorMissingType"];
export declare type IsIntersectionRepresentable<A> = IsRepresentable<ClearIntersections<A>>;

@@ -1,3 +0,5 @@

import { DoesExtend, Get, DeepMergeUnsafe } from "../utils";
import { Resolve, Any } from ".";
import { A, B } from "ts-toolbelt";
import { DoesExtend, Or, Not, Get, DeepMergeUnsafe } from "../utils";
import { Resolve, Any, Never } from ".";
import { IsRepresentable } from "./utils";
export declare type ObjectType = "object";

@@ -12,2 +14,3 @@ export declare type Object<V = {}, R = never, O = true, P = Any> = {

export declare type Values<O> = Get<O, "values">;
export declare type Value<O, K> = K extends keyof Values<O> ? Values<O>[K] : IsOpen<O> extends true ? OpenProps<O> : Never;
export declare type Required<O> = Get<O, "required"> extends string ? Get<O, "required"> : never;

@@ -28,2 +31,6 @@ export declare type IsOpen<O> = Get<O, "isOpen">;

}>>;
declare type IsObjectValueRepresentable<O, K> = K extends keyof Values<O> ? IsRepresentable<Values<O>[K]> : IsOpen<O> extends true ? IsRepresentable<OpenProps<O>> : false;
export declare type IsObjectRepresentable<O> = Or<DoesExtend<A.Equals<Required<O>, never>, B.True>, Not<DoesExtend<false, {
[key in Required<O>]: IsObjectValueRepresentable<O, key>;
}[Required<O>]>>>;
export {};
import { Get, Head, Tail, Prepend, Concat, Reverse } from "../utils";
import { Resolve, Any } from ".";
import { IsRepresentable } from "./utils";
export declare type TupleType = "tuple";

@@ -18,2 +19,7 @@ export declare type Tuple<V, O = true, P = Any> = {

}[V extends [any, ...any[]] ? "continue" : "stop"];
export declare type IsTupleRepresentable<T> = AreAllTupleValuesRepresentable<Values<T>>;
declare type AreAllTupleValuesRepresentable<V> = {
stop: true;
continue: V extends any[] ? IsRepresentable<Head<V>> extends false ? false : AreAllTupleValuesRepresentable<Tail<V>> : never;
}[V extends [any, ...any[]] ? "continue" : "stop"];
export {};

@@ -1,3 +0,4 @@

import { Get } from "../utils";
import { DoesExtend, Get } from "../utils";
import { Resolve } from ".";
import { IsRepresentable } from "./utils";
export declare type UnionType = "union";

@@ -9,4 +10,6 @@ export declare type Union<V> = {

export declare type Values<U> = Get<U, "values">;
export declare type ResolveUnion<T> = RecurseOnUnionTree<Values<T>>;
declare type RecurseOnUnionTree<V> = V extends infer T ? Resolve<T> : never;
export declare type ResolveUnion<U> = RecurseOnUnion<Values<U>>;
declare type RecurseOnUnion<V> = V extends infer T ? Resolve<T> : never;
export declare type IsUnionRepresentable<U> = DoesExtend<true, AreUnionValuesRepresentable<Values<U>>>;
declare type AreUnionValuesRepresentable<V> = V extends infer T ? IsRepresentable<T> : never;
export {};
import { Any, Intersection } from "../meta-types";
import { Tail, Head, Get, HasKeyIn, Merge } from "../utils";
import { Tail, Head, Get, HasKeyIn } from "../utils";
import { ParseSchema } from ".";
import { RemoveInvalidAdditionalItems } from "./utils";
import { MergeSubSchema } from "./utils";
export declare type ParseAllOfSchema<S> = RecurseOnAllOfSchema<Get<S, "allOf">, S, HasKeyIn<S, "enum" | "const" | "type" | "anyOf" | "oneOf"> extends true ? ParseSchema<Omit<S, "allOf">> : Any>;
declare type RecurseOnAllOfSchema<V, S, R> = {
stop: R;
continue: V extends any[] ? RecurseOnAllOfSchema<Tail<V>, S, Intersection<ParseSchema<Merge<Omit<S, "allOf">, Merge<{
properties: {};
additionalProperties: true;
required: [];
}, RemoveInvalidAdditionalItems<Head<V>>>>>, R>> : never;
continue: V extends any[] ? RecurseOnAllOfSchema<Tail<V>, S, Intersection<ParseSchema<MergeSubSchema<Omit<S, "allOf">, Head<V>>>, R>> : never;
}[V extends [any, ...any[]] ? "continue" : "stop"];
export {};
import { Intersection, Union } from "../meta-types";
import { Tail, Head, Get, HasKeyIn, Merge } from "../utils";
import { ParseSchema } from ".";
import { RemoveInvalidAdditionalItems } from "./utils";
import { MergeSubSchema, RemoveInvalidAdditionalItems } from "./utils";
export declare type ParseAnyOfSchema<S> = Union<RecurseOnAnyOfSchema<Get<S, "anyOf">, S>>;
declare type RecurseOnAnyOfSchema<S, P, R = never> = {
stop: R;
continue: S extends any[] ? RecurseOnAnyOfSchema<Tail<S>, P, R | (HasKeyIn<P, "enum" | "const" | "type"> extends true ? Intersection<ParseSchema<Omit<P, "anyOf">>, ParseSchema<Merge<Omit<P, "anyOf">, Merge<{
properties: {};
additionalProperties: true;
required: [];
}, RemoveInvalidAdditionalItems<Head<S>>>>>> : ParseSchema<Merge<Omit<P, "anyOf">, RemoveInvalidAdditionalItems<Head<S>>>>)> : never;
continue: S extends any[] ? RecurseOnAnyOfSchema<Tail<S>, P, R | (HasKeyIn<P, "enum" | "const" | "type"> extends true ? Intersection<ParseSchema<Omit<P, "anyOf">>, ParseSchema<MergeSubSchema<Omit<P, "anyOf">, Head<S>>>> : ParseSchema<Merge<Omit<P, "anyOf">, RemoveInvalidAdditionalItems<Head<S>>>>)> : never;
}[S extends [any, ...any[]] ? "continue" : "stop"];
export {};

@@ -11,2 +11,3 @@ import { Primitive, Any, Never } from "../meta-types";

import { ParseNotSchema } from "./not";
import { ParseIfThenElseSchema } from "./ifThenElse";
export declare type ParseSchema<S> = {

@@ -28,4 +29,5 @@ any: Any;

not: ParseNotSchema<S>;
ifThenElse: ParseIfThenElseSchema<S>;
}[InferSchemaType<S>];
declare type InferSchemaType<S> = S extends true | string ? "any" : S extends false ? "never" : "not" extends keyof S ? "not" : "allOf" extends keyof S ? "allOf" : "oneOf" extends keyof S ? "oneOf" : "anyOf" extends keyof S ? "anyOf" : "enum" extends keyof S ? "enum" : "const" extends keyof S ? "const" : "type" extends keyof S ? S["type"] extends any[] ? "mixed" : S["type"] extends "null" ? "null" : S["type"] extends "boolean" ? "boolean" : S["type"] extends "integer" | "number" ? "number" : S["type"] extends "string" ? "string" : S["type"] extends "object" ? "object" : S["type"] extends "array" ? "array" : "never" : "any";
declare type InferSchemaType<S> = S extends true | string ? "any" : S extends false ? "never" : "if" extends keyof S ? "ifThenElse" : "not" extends keyof S ? "not" : "allOf" extends keyof S ? "allOf" : "oneOf" extends keyof S ? "oneOf" : "anyOf" extends keyof S ? "anyOf" : "enum" extends keyof S ? "enum" : "const" extends keyof S ? "const" : "type" extends keyof S ? S["type"] extends any[] ? "mixed" : S["type"] extends "null" ? "null" : S["type"] extends "boolean" ? "boolean" : S["type"] extends "integer" | "number" ? "number" : S["type"] extends "string" ? "string" : S["type"] extends "object" ? "object" : S["type"] extends "array" ? "array" : "never" : "any";
export {};

@@ -1,6 +0,8 @@

import { Exclusion, Union, Any, Primitive, Arr, Object } from "../meta-types";
import { Get, HasKeyIn, Merge } from "../utils";
import { Any, Primitive, Arr, Object, Union, Exclusion } from "../meta-types";
import { IsRepresentable } from "../meta-types/utils";
import { Get, HasKeyIn } from "../utils";
import { ParseSchema } from ".";
import { MergeSubSchema } from "./utils";
declare type AllTypes = Union<Primitive<null> | Primitive<boolean> | Primitive<number> | Primitive<string> | Arr<Any> | Object>;
export declare type ParseNotSchema<S> = Exclusion<HasKeyIn<S, "enum" | "const" | "type" | "anyOf" | "oneOf" | "allOf"> extends true ? ParseSchema<Omit<S, "not">> : AllTypes, ParseSchema<Merge<Omit<S, "not">, Get<S, "not">>>>;
export declare type ParseNotSchema<S, P = ParseSchema<Omit<S, "not">>, E = Exclusion<HasKeyIn<S, "enum" | "const" | "type" | "anyOf" | "oneOf" | "allOf"> extends true ? P : AllTypes, ParseSchema<MergeSubSchema<Omit<S, "not">, Get<S, "not">>>>> = IsRepresentable<E> extends true ? E : P;
export {};
import { Intersection, Union } from "../meta-types";
import { Tail, Head, Get, HasKeyIn, Merge } from "../utils";
import { ParseSchema } from ".";
import { RemoveInvalidAdditionalItems } from "./utils";
import { MergeSubSchema, RemoveInvalidAdditionalItems } from "./utils";
export declare type ParseOneOfSchema<S> = Union<RecurseOnOneOfSchema<Get<S, "oneOf">, S>>;
declare type RecurseOnOneOfSchema<S, P, R = never> = {
stop: R;
continue: S extends any[] ? RecurseOnOneOfSchema<Tail<S>, P, R | (HasKeyIn<P, "enum" | "const" | "type" | "anyOf"> extends true ? Intersection<ParseSchema<Omit<P, "oneOf">>, ParseSchema<Merge<Omit<P, "oneOf">, Merge<{
properties: {};
additionalProperties: true;
required: [];
}, RemoveInvalidAdditionalItems<Head<S>>>>>> : ParseSchema<Merge<Omit<P, "oneOf">, RemoveInvalidAdditionalItems<Head<S>>>>)> : never;
continue: S extends any[] ? RecurseOnOneOfSchema<Tail<S>, P, R | (HasKeyIn<P, "enum" | "const" | "type" | "anyOf"> extends true ? Intersection<ParseSchema<Omit<P, "oneOf">>, ParseSchema<MergeSubSchema<Omit<P, "oneOf">, Head<S>>>> : ParseSchema<Merge<Omit<P, "oneOf">, RemoveInvalidAdditionalItems<Head<S>>>>)> : never;
}[S extends [any, ...any[]] ? "continue" : "stop"];
export {};

@@ -5,1 +5,6 @@ import { Merge } from "../utils";

}> : Omit<S, "additionalItems">;
export declare type MergeSubSchema<P, C> = Merge<P, Merge<{
properties: {};
additionalProperties: true;
required: [];
}, RemoveInvalidAdditionalItems<C>>>;

@@ -9,3 +9,5 @@ export { And } from "./and";

export { DeepMergeSafe, DeepMergeUnsafe, Merge } from "./merge";
export { Not } from "./not";
export { OptionalProps } from "./optionalProps";
export { Or } from "./or";
export { Prepend } from "./prepend";

@@ -12,0 +14,0 @@ export { Prettify } from "./prettify";

{
"name": "json-schema-to-ts",
"version": "1.5.0",
"version": "1.6.0",
"description": "Infer typescript types from your JSON schemas!",
"main": "lib/index.d.ts",
"scripts": {
"build": "tsc --emitDeclarationOnly --declaration --declarationDir lib ./src/*.ts",
"build": "rm -rf lib && tsc --emitDeclarationOnly --declaration --declarationDir lib ./src/*.ts",
"test": "tsc --noEmit && jest --verbose"
},
"dependencies": {
"@types/json-schema": "^7.0.6"
"@types/json-schema": "^7.0.6",
"ts-toolbelt": "^6.15.5"
},

@@ -13,0 +14,0 @@ "devDependencies": {

@@ -134,3 +134,5 @@ <img src="assets/header-round-medium.png" width="100%" align="center" />

- [OneOf](#oneof)
- [Not and If-Then-Else](#not-and-if-then-else)
- [Not](#not)
- [If/Then/Else](#ifthenelse)
- [Definitions](#definitions)

@@ -294,3 +296,3 @@ ## Installation

- `additionalProperties` can be used to deny additional items.
- `additionalProperties` can be used to deny additional properties.

@@ -384,3 +386,3 @@ ```typescript

Because TypeScript misses [refinment types](https://en.wikipedia.org/wiki/Refinement_type), `FromSchema` will use the `oneOf` keyword in the same way as `anyOf`:
For the moment, `FromSchema` will use the `oneOf` keyword in the same way as `anyOf`:

@@ -414,6 +416,8 @@ ```typescript

// => FromSchema will not detect the following invalid obj 😱
// => Error will NOT be raised 😱
const invalidCat: Cat = { name: "Garfield" };
```
> This may be revised soon now that `not` exclusions are now possible
### AllOf

@@ -478,5 +482,64 @@

Keep in mind that the `not` type computation uses the `Exclude` utility type, which suffers from Typescript's limitations:
In objects and tuples, the exclusion will propagate to properties/items if it can collapse on a single one.
```typescript
// 👍 Can be propagated on "animal" property
const petSchema = {
type: "object",
properties: {
animal: { enum: ["cat", "dog", "boat"] },
},
not: {
properties: { animal: { const: "boat" } },
},
required: ["animal"],
additionalProperties: false,
} as const;
type Pet = FromSchema<typeof petSchema>;
// => { animal: "cat" | "dog" }
```
```typescript
// ❌ Cannot be propagated
const petSchema = {
type: "object",
properties: {
animal: { enum: ["cat", "dog"] },
color: { enum: ["black", "brown", "white"] },
},
not: {
const: { animal: "cat", color: "white" },
},
required: ["animal", "color"],
additionalProperties: false,
} as const;
type Pet = FromSchema<typeof petSchema>;
// => { animal: "cat" | "dog", color: "black" | "brown" | "white" }
```
As some actionable keywords are not yet parsed, exclusions that resolve to `never` are granted the benefit of the doubt and omitted. For the moment, `FromSchema` assumes that you are not crafting unvalidatable exclusions.
```typescript
const oddNumberSchema = {
type: "number",
not: { multipleOf: 2 },
} as const;
type OddNumber = FromSchema<typeof oddNumberSchema>;
// => should and will resolve to "number"
const incorrectSchema = {
type: "number",
not: { bogus: "option" },
} as const;
type Incorrect = FromSchema<typeof incorrectSchema>;
// => should resolve to "never" but will still resolve to "number"
```
Also, keep in mind that TypeScript misses [refinment types](https://en.wikipedia.org/wiki/Refinement_type):
```typescript
const goodLanguageSchema = {

@@ -493,4 +556,40 @@ type: "string",

### If-Then-Else
### If/Then/Else
The `if/then/else` keyword is not implemented yet.
```typescript
const petSchema = {
type: "object",
properties: {
animal: { enum: ["cat", "dog"] },
dogBreed: { enum: Object.values(DogBreed) },
catBreed: { enum: Object.values(CatBreed) },
},
required: ["animal"],
additionalProperties: false,
if: {
properties: {
animal: { const: "dog" },
},
},
then: {
required: ["dogBreed"],
not: { required: ["catBreed"] },
},
else: {
required: ["catBreed"],
not: { required: ["dogBreed"] },
},
} as const;
type Pet = FromSchema<typeof petSchema>;
// => { animal: "dog"; dogBreed: DogBreed }
// | { animal: "cat"; catBreed: CatBreed }
```
> `FromSchema` computes the resulting type as `(If ∩ Then) ∪ (¬If ∩ Else)`. While correct in theory, remember that the `not` keyword is not perfectly assimilated, which may become an issue in some complex schemas.
## Definitions
Since the introduction of [template literal types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html) with Typescript 4.1, the `definitions` keyword seems implementable in `json-schema-to-ts`.
I'll soon be looking into it. Meanwhile, feel free to [open an issue](https://github.com/ThomasAribart/json-schema-to-ts/issues) 🤗
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc