json-schema-to-ts
Advanced tools
Comparing version 0.1.8 to 0.1.9
{ | ||
"name": "json-schema-to-ts", | ||
"version": "0.1.8", | ||
"version": "0.1.9", | ||
"description": "Infer typescript types from your JSON schemas!", | ||
@@ -5,0 +5,0 @@ "main": "src/index.ts", |
@@ -73,3 +73,3 @@ # Stop typing twice 🙅♂️ | ||
**Note**: The `as const` statement is used so that TypeScript takes the schema definition to the word (e.g. _true_ is interpreted as the _true_ constant and not as _boolean_). It is pure TypeScript and has zero impact on the compiled code. | ||
**Note**: The `as const` statement is used so that TypeScript takes the schema definition to the word (e.g. _true_ is interpreted as the _true_ constant and not widened as _boolean_). It is pure TypeScript and has zero impact on the compiled code. | ||
@@ -303,5 +303,1 @@ # Docs | ||
``` | ||
``` | ||
``` |
import { FromWriteableSchema } from "./index"; | ||
import { Tail, Head } from "./utils"; | ||
/** | ||
* Given a JSON schema with the `anyOf` property, infers the type of valid instances | ||
* | ||
* Args: | ||
* - `Schema`: JSON schema | ||
*/ | ||
export type FromAnyOfSchema<S> = "anyOf" extends keyof S | ||
@@ -12,7 +18,15 @@ ? S["anyOf"] extends any[] | ||
type RecurseOnAnyOfSchema<S, T = unknown, R = never> = { | ||
stop: R & T; | ||
/** | ||
* Given an tuple of JSON schema, returns the union of inferred types (can be intersected with a filter type) | ||
* | ||
* Args: | ||
* - `Schemas`: Tuple of JSON schemas to recurse on | ||
* - `Filter`: _(optional)_ Filter type (intersected with the result) | ||
* - `Result`: _(optional)_ Accumulated result | ||
*/ | ||
type RecurseOnAnyOfSchema<S, F = unknown, R = never> = { | ||
stop: R & F; | ||
continue: S extends any[] | ||
? RecurseOnAnyOfSchema<Tail<S>, T, R | FromWriteableSchema<Head<S>>> | ||
? RecurseOnAnyOfSchema<Tail<S>, F, R | FromWriteableSchema<Head<S>>> | ||
: never; | ||
}[S extends [any, ...any[]] ? "continue" : "stop"]; |
@@ -13,2 +13,8 @@ import { FromWriteableSchema } from "./index"; | ||
/** | ||
* Given a JSON schema of `array` type, infers the type of valid instances | ||
* | ||
* Args: | ||
* - `Schema`: JSON schema | ||
*/ | ||
export type FromArraySchema<S> = "items" extends keyof S | ||
@@ -22,13 +28,27 @@ ? S["items"] extends Schema | ||
type GetTypesTuple<I, R extends any[] = []> = { | ||
/** | ||
* Given a tuple of JSON schemas, returns the (reversed) tuple of inferred types | ||
* | ||
* Args: | ||
* - `Shemas`: Tuple of JSON schemas | ||
* - `Result`: _(optional)_ Accumulated result | ||
*/ | ||
type GetTypesTuple<S, R extends any[] = []> = { | ||
stop: R; | ||
continue: I extends any[] | ||
? GetTypesTuple<Tail<I>, Prepend<FromWriteableSchema<Head<I>>, R>> | ||
continue: S extends any[] | ||
? GetTypesTuple<Tail<S>, Prepend<FromWriteableSchema<Head<S>>, R>> | ||
: never; | ||
}[I extends [any, ...any[]] ? "continue" : "stop"]; | ||
}[S extends [any, ...any[]] ? "continue" : "stop"]; | ||
type FromTypesTuple<I, S> = I extends any[] | ||
/** | ||
* Apply a JSON schema `additionalItems`, `minItems` & `maxItems` directives to a (reversed) tuple of types | ||
* | ||
* Args: | ||
* - `Types`: Tuple of types | ||
* - `Schema`: JSON schema | ||
*/ | ||
type FromTypesTuple<T, S> = T extends any[] | ||
? ApplyAdditionalItems< | ||
ApplyBoundaries< | ||
I, | ||
T, | ||
"minItems" extends keyof S ? S["minItems"] : 0, | ||
@@ -41,2 +61,19 @@ "maxItems" extends keyof S ? S["maxItems"] : undefined | ||
/** | ||
* Given a tuple, a min and a max integer values, returns the data needed to infer a tuple schema valid instance type | ||
* | ||
* Args: | ||
* - `Tuple`: Tuple of types to recurse on (reversed) | ||
* - `Min`: Minimum length of a valid extracted tuple | ||
* - `Max`: Maximum length of a valid extracted tuple _(possibly undefined)_ | ||
* - `Result`: _(optional)_ Union of the extracted tuples of valid length _(possibly_ `never` _)_ | ||
* - `HasMin`: _(optional)_ True if `Tuple` has had a length equal to `Min` during recursion | ||
* - `HasMax`: _(optional)_ True if `Tuple` has had a length equal to `Max` during recursion | ||
* - `CompleteTuple`: _(optional)_ Memorized initial value of `Tuple` | ||
* | ||
* Returns: | ||
* - `result` Union of the extracted tuples of valid length _(possibly_ `never` _)_ | ||
* - `completeTuple` Memorized initial value of `Tuple` | ||
* - `hasEncounteredMax`: True if `Tuple` has had a length equal to `Max` during recursion | ||
*/ | ||
type ApplyBoundaries< | ||
@@ -58,3 +95,3 @@ T extends any[], | ||
? Reverse<T> | ||
: AreBoundariesInvalid<Tail<T>, Max> extends true | ||
: IsLongerThan<Tail<T>, Max> extends true | ||
? never | ||
@@ -66,3 +103,3 @@ : R | Reverse<T>; | ||
? true | ||
: AreBoundariesInvalid<Tail<T>, Max>; | ||
: IsLongerThan<Tail<T>, Max>; | ||
completeTuple: C; | ||
@@ -85,9 +122,22 @@ }; | ||
type AreBoundariesInvalid<T extends any[], Max, R = true> = { | ||
continue: T["length"] extends Max | ||
? AreBoundariesInvalid<Tail<T>, Max> | ||
: false; | ||
stop: T["length"] extends Max ? R : false; | ||
/** | ||
* Given a tuple and an integer value, returns true if tuple is longer than the value | ||
* | ||
* Args: | ||
* - `Tuple`: Tuple | ||
* - `Number`: Integer value _(possibly undefined)_ | ||
* - `Result`: _(optional)_ Accumulated result | ||
*/ | ||
type IsLongerThan<T extends any[], N, R = true> = { | ||
continue: T["length"] extends N ? IsLongerThan<Tail<T>, N> : false; | ||
stop: T["length"] extends N ? R : false; | ||
}[T extends [any, ...any[]] ? "continue" : "stop"]; | ||
/** | ||
* Given the return value of `ApplyBoundaries`, and the `additionalItems` value of a tuple schema, returns the inferred type | ||
* | ||
* Args: | ||
* - `Result`: Return value of `ApplyBoundaries` | ||
* - `AdditionalItems`: Accumulated result | ||
*/ | ||
type ApplyAdditionalItems<R, A> = Get<R, "hasEncounteredMax"> extends true | ||
@@ -94,0 +144,0 @@ ? Get<R, "result"> |
import { FromWriteableSchema } from "./index"; | ||
/** | ||
* Given a JSON schema with the `const` property, returns the type of valid instances | ||
* | ||
* Args: | ||
* - `Schema`: JSON schema | ||
*/ | ||
export type FromConstSchema<S> = "const" extends keyof S | ||
@@ -4,0 +10,0 @@ ? "type" extends keyof S |
import { FromWriteableSchema } from "./index"; | ||
import { Head, Tail } from "./utils"; | ||
/** | ||
* Given a JSON schema with the `enum` property, infers the type of valid instances | ||
* | ||
* Args: | ||
* - `Schema`: JSON schema | ||
*/ | ||
export type FromEnumSchema<S> = "enum" extends keyof S | ||
@@ -12,9 +18,17 @@ ? S["enum"] extends any[] | ||
type RecurseOnEnumSchema<S, T = any, R = never> = { | ||
/** | ||
* Given an enum, returns the union of its values that match a specified type | ||
* | ||
* Args: | ||
* - `Enum`: Enum to recurse on | ||
* - `FilterType`: _(optional)_ Removes enum values that don't extend it from result | ||
* - `Result`: _(optional)_ Accumulated result | ||
*/ | ||
type RecurseOnEnumSchema<S, F = any, R = never> = { | ||
stop: number extends keyof S ? S[number] | R : R; | ||
continue: S extends any[] | ||
? Head<S> extends T | ||
? RecurseOnEnumSchema<Tail<S>, T, R | Head<S>> | ||
: RecurseOnEnumSchema<Tail<S>, T, R> | ||
? Head<S> extends F | ||
? RecurseOnEnumSchema<Tail<S>, F, R | Head<S>> | ||
: RecurseOnEnumSchema<Tail<S>, F, R> | ||
: never; | ||
}[S extends [any, ...any[]] ? "continue" : "stop"]; |
import { FromAnyOfSchema } from "./anyOf"; | ||
import { FromEnumSchema } from "./enum"; | ||
import { FromConstSchema } from "./const"; | ||
import { FromMultipleSchema } from "./multiple"; | ||
import { FromMixedSchema } from "./mixed"; | ||
import { FromObjectSchema } from "./object"; | ||
@@ -9,2 +9,8 @@ import { FromArraySchema } from "./array"; | ||
/** | ||
* Given a JSON schema defined with the `as const` statement, infers the type of valid instances | ||
* | ||
* Args: | ||
* - `Schema`: JSON schema | ||
*/ | ||
export type FromSchema<S> = FromReadonlySchema<S>; | ||
@@ -20,3 +26,3 @@ | ||
const: FromConstSchema<S>; | ||
multiple: FromMultipleSchema<S>; | ||
mixed: FromMixedSchema<S>; | ||
null: null; | ||
@@ -44,3 +50,3 @@ boolean: boolean; | ||
? S["type"] extends any[] | ||
? "multiple" | ||
? "mixed" | ||
: S["type"] extends "null" | ||
@@ -47,0 +53,0 @@ ? "null" |
@@ -5,2 +5,8 @@ import { FromWriteableSchema } from "./index"; | ||
/** | ||
* Given a JSON schema of `object` type, infers the type of valid instances | ||
* | ||
* Args: | ||
* - `Schema`: JSON schema | ||
*/ | ||
export type FromObjectSchema<S> = S extends ObjectSchema | ||
@@ -48,2 +54,8 @@ ? "properties" extends keyof S | ||
/** | ||
* Given the `additionalProperties` value of an object JSON schema, returns the inferred type | ||
* | ||
* Args: | ||
* - `AdditionalProps`: Value of an object JSON schema `additionalProperties` | ||
*/ | ||
type AdditionalProps<A> = A extends false | ||
@@ -57,2 +69,8 @@ ? { [key: string]: never } | ||
/** | ||
* Given the `patternProperties` value of an object JSON schema, returns the inferred type | ||
* | ||
* Args: | ||
* - `PatternProps`: Value of an object JSON schema `patternProperties` | ||
*/ | ||
type PatternProps<P> = { | ||
@@ -64,2 +82,9 @@ [key: string]: { | ||
/** | ||
* Given the `additionalProperties` and `patternProperties` value of an object JSON schema, returns the inferred type | ||
* | ||
* Args: | ||
* - `AdditionalProps`: Value of an object JSON schema `additionalProperties` | ||
* - `PatternProps`: Value of an object JSON schema `patternProperties` | ||
*/ | ||
type AdditionalAndPatternProps<A, P> = A extends boolean | ||
@@ -66,0 +91,0 @@ ? PatternProps<P> |
@@ -5,7 +5,14 @@ import { Head } from "./head"; | ||
export type ConcatReversed<T, R extends any[]> = { | ||
stop: R; | ||
continue: T extends any[] | ||
? ConcatReversed<Tail<T>, Prepend<Head<T>, R>> | ||
/** | ||
* Concatenate the reverse of tuple `A` to tuple `B` | ||
* | ||
* Args: | ||
* - `A`: Tuple `A` | ||
* - `B`: Tuple `B` | ||
*/ | ||
export type ConcatReversed<A, B extends any[]> = { | ||
stop: B; | ||
continue: A extends any[] | ||
? ConcatReversed<Tail<A>, Prepend<Head<A>, B>> | ||
: never; | ||
}[T extends [any, ...any[]] ? "continue" : "stop"]; | ||
}[A extends [any, ...any[]] ? "continue" : "stop"]; |
@@ -0,5 +1,19 @@ | ||
/** | ||
* Returns `true` if type `A` extends type `B`, `false` if not | ||
* | ||
* Args: | ||
* - `A`: Type `A` | ||
* - `B`: Type `B` | ||
*/ | ||
export type DoesExtend<A, B> = A extends B ? true : false; | ||
/** | ||
* Returns `true` if both types extend each other, `false` if not | ||
* | ||
* Args: | ||
* - `A`: Type `A` | ||
* - `B`: Type `B` | ||
*/ | ||
export type DoesBothExtend<A, B> = DoesExtend<A, B> extends true | ||
? DoesExtend<B, A> | ||
: false; |
@@ -0,1 +1,8 @@ | ||
/** | ||
* Returns the property of an object, `never` if property misses from object | ||
* | ||
* Args: | ||
* - `Object`: Object | ||
* - `Property`: Property name | ||
*/ | ||
export type Get<O, P extends string> = P extends keyof O ? O[P] : never; |
@@ -0,1 +1,7 @@ | ||
/** | ||
* Returns the first element of a tuple | ||
* | ||
* Args: | ||
* - `Tuple`: Tuple | ||
*/ | ||
export type Head<T extends any[]> = T[0]; |
@@ -7,5 +7,4 @@ export { Get } from "./get"; | ||
export { ConcatReversed } from "./concat"; | ||
export { ShortenReversed } from "./shorten"; | ||
export { MergeRight } from "./merge"; | ||
export { Writeable } from "./writeable"; | ||
export { DoesExtend, DoesBothExtend } from "./extends"; |
@@ -0,1 +1,10 @@ | ||
/** | ||
* Merge two types `A` and `B`: | ||
* - Returns `B` if `A` or `B` is not an object | ||
* - Recursively merge `A` and `B` properties if both are objects | ||
* | ||
* Args: | ||
* - `A`: Type `A` | ||
* - `B`: Type `B` | ||
*/ | ||
export type MergeRight<A, B> = A extends object | ||
@@ -2,0 +11,0 @@ ? B extends object |
@@ -1,3 +0,10 @@ | ||
export type Prepend<H, T extends any[]> = (( | ||
head: H, | ||
/** | ||
* Inserts an element at the start of a tuple | ||
* | ||
* Args: | ||
* - `Element`: Element to insert | ||
* - `Tuple`: Tuple | ||
*/ | ||
export type Prepend<E, T extends any[]> = (( | ||
element: E, | ||
...tail: T | ||
@@ -4,0 +11,0 @@ ) => void) extends (...tuple: infer R) => void |
@@ -5,2 +5,9 @@ import { Head } from "./head"; | ||
/** | ||
* Reverses a tuple | ||
* | ||
* Args: | ||
* - `Tuple`: Tuple | ||
* - `Result`: _(optional)_ Reversed tuple | ||
*/ | ||
export type Reverse<T extends any[], R extends any[] = []> = { | ||
@@ -7,0 +14,0 @@ stop: R; |
@@ -0,1 +1,7 @@ | ||
/** | ||
* Remove the first element of a tuple | ||
* | ||
* Args: | ||
* - `Tuple`: Tuple | ||
*/ | ||
export type Tail<T extends any[]> = ((...args: T) => void) extends ( | ||
@@ -2,0 +8,0 @@ head: any, |
@@ -1,3 +0,9 @@ | ||
export type Writeable<A> = A extends object | ||
? { -readonly [K in keyof A]: Writeable<A[K]> } | ||
: A; | ||
/** | ||
* Recursively remove the `readonly` directive from an object properties | ||
* | ||
* Args: | ||
* - `Object`: Object | ||
*/ | ||
export type Writeable<O> = O extends object | ||
? { -readonly [K in keyof O]: Writeable<O[K]> } | ||
: O; |
26542
624
21
302