Skip to content

Commit

Permalink
JSONSchemaType for definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Sep 14, 2020
1 parent 4ff2135 commit ca74224
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 32 deletions.
19 changes: 15 additions & 4 deletions lib/types/json-schema.ts
@@ -1,3 +1,8 @@
/* eslint-disable @typescript-eslint/no-empty-interface */
export type SomeJSONSchema = JSONSchemaType<Known, true>

export type PartialSchema<T> = Partial<JSONSchemaType<T, true>>

export type JSONSchemaType<T, Partial = false> = (T extends number
? {
type: "number" | "integer"
Expand Down Expand Up @@ -51,7 +56,7 @@ export type JSONSchemaType<T, Partial = false> = (T extends number
required: Partial extends true ? (keyof T)[] : RequiredMembers<T>[]
additionalProperties: boolean | JSONSchemaType<T[string]>
properties?: {
[K in keyof T]-?: JSONSchemaType<T[K]> & Nullable<T[K]>
[K in keyof T]-?: (JSONSchemaType<T[K]> & Nullable<T[K]>) | {$ref: string}
}
patternProperties?: {
[pattern: string]: JSONSchemaType<T[string]>
Expand All @@ -71,8 +76,12 @@ export type JSONSchemaType<T, Partial = false> = (T extends number
[keyword: string]: any
$id?: string
$ref?: string
$defs?: {[key: string]: JSONSchemaType<any>}
definitions?: {[key: string]: JSONSchemaType<any>}
$defs?: {
[key: string]: JSONSchemaType<Known, true>
}
definitions?: {
[key: string]: JSONSchemaType<Known, true>
}
allOf?: PartialSchema<T>[]
anyOf?: PartialSchema<T>[]
oneOf?: PartialSchema<T>[]
Expand All @@ -82,7 +91,9 @@ export type JSONSchemaType<T, Partial = false> = (T extends number
not?: PartialSchema<T>
}

type PartialSchema<T> = Partial<JSONSchemaType<T, true>>
type Known = KnownRecord | [Known, ...Known[]] | Known[] | number | string | boolean | null

interface KnownRecord extends Record<string, Known> {}

type RequiredMembers<T> = {
[K in keyof T]-?: undefined extends T[K] ? never : K
Expand Down
69 changes: 41 additions & 28 deletions spec/types/json-schema.spec.ts
Expand Up @@ -10,22 +10,37 @@ interface MyData {
[x: string]: string
}
boo?: true
arr: {id: number}[]
tuple?: [number, string]
arr: {id: number}[]
map: {[x: string]: number}
notBoo?: string // should not be present if "boo" is present
}

const mySchema: JSONSchemaType<MyData> = {
type: "object",
dependencies: {
bar: ["boo"],
boo: {not: {required: ["notBoo"]}},
const arrSchema: JSONSchemaType<MyData["arr"]> = {
type: "array",
items: {
type: "object",
properties: {
id: {
type: "integer",
},
},
additionalProperties: false,
required: ["id"],
},
properties: {
foo: {type: "string"},
bar: {type: "number", nullable: true},
uniqueItems: true,
}

const mySchema: JSONSchemaType<MyData> & {
definitions: {
baz: JSONSchemaType<MyData["baz"]>
tuple: JSONSchemaType<MyData["tuple"]>
}
} = {
type: "object",
definitions: {
baz: {
// schema type is checked here ...
type: "object",
properties: {
quux: {type: "string", const: "quux"},
Expand All @@ -36,32 +51,30 @@ const mySchema: JSONSchemaType<MyData> = {
additionalProperties: false,
required: [],
},
boo: {
type: "boolean",
nullable: true,
enum: [true, null],
},
arr: {
type: "array",
items: {
type: "object",
properties: {
id: {
type: "integer",
},
},
additionalProperties: false,
required: ["id"],
},
uniqueItems: true,
},
tuple: {
// ... and here ...
type: "array",
items: [{type: "number"}, {type: "string"}],
minItems: 2,
additionalItems: false,
nullable: true,
},
},
dependencies: {
bar: ["boo"],
boo: {not: {required: ["notBoo"]}}, // optional properties can be cheched in required in PartialSchema
},
properties: {
foo: {type: "string"},
bar: {type: "number", nullable: true},
baz: {$ref: "#/definitions/baz"}, // ... but it does not check type here, ...
boo: {
type: "boolean",
nullable: true,
enum: [true, null],
},
tuple: {$ref: "#/definitions/tuple"}, // ... nor here.
arr: arrSchema, // ... The alternative is to define it externally - here it checks type
map: {
type: "object",
required: [],
Expand Down

0 comments on commit ca74224

Please sign in to comment.