11/* eslint-disable @typescript-eslint/no-empty-interface */
2- export type SomeJSONSchema = JSONSchemaType < Known , true >
2+ type StrictNullChecksWrapper < Name extends string , Type > = undefined extends null
3+ ? `strictNullChecks must be true in tsconfig to use ${Name } `
4+ : Type
35
4- export type PartialSchema < T > = Partial < JSONSchemaType < T , true > >
6+ export type SomeJSONSchema = UncheckedJSONSchemaType < Known , true >
57
6- type JSONType < T extends string , _partial extends boolean > = _partial extends true
8+ type UncheckedPartialSchema < T > = Partial < UncheckedJSONSchemaType < T , true > >
9+
10+ export type PartialSchema < T > = StrictNullChecksWrapper < "PartialSchema" , UncheckedPartialSchema < T > >
11+
12+ type JSONType < T extends string , IsPartial extends boolean > = IsPartial extends true
713 ? T | undefined
814 : T
915
@@ -23,22 +29,22 @@ interface StringKeywords {
2329 format ?: string
2430}
2531
26- export type JSONSchemaType < T , _partial extends boolean = false > = (
32+ type UncheckedJSONSchemaType < T , IsPartial extends boolean > = (
2733 | // these two unions allow arbitrary unions of types
2834 {
29- anyOf : readonly JSONSchemaType < T , _partial > [ ]
35+ anyOf : readonly UncheckedJSONSchemaType < T , IsPartial > [ ]
3036 }
3137 | {
32- oneOf : readonly JSONSchemaType < T , _partial > [ ]
38+ oneOf : readonly UncheckedJSONSchemaType < T , IsPartial > [ ]
3339 }
3440 // this union allows for { type: (primitive)[] } style schemas
3541 | ( {
3642 type : ( T extends number
37- ? JSONType < "number" | "integer" , _partial >
43+ ? JSONType < "number" | "integer" , IsPartial >
3844 : T extends string
39- ? JSONType < "string" , _partial >
45+ ? JSONType < "string" , IsPartial >
4046 : T extends boolean
41- ? JSONType < "boolean" , _partial >
47+ ? JSONType < "boolean" , IsPartial >
4248 : never ) [ ]
4349 } & ( T extends number
4450 ? NumberKeywords
@@ -50,11 +56,11 @@ export type JSONSchemaType<T, _partial extends boolean = false> = (
5056 // this covers "normal" types; it's last so typescript looks to it first for errors
5157 | ( ( T extends number
5258 ? {
53- type : JSONType < "number" | "integer" , _partial >
59+ type : JSONType < "number" | "integer" , IsPartial >
5460 } & NumberKeywords
5561 : T extends string
5662 ? {
57- type : JSONType < "string" , _partial >
63+ type : JSONType < "string" , IsPartial >
5864 } & StringKeywords
5965 : T extends boolean
6066 ? {
@@ -63,17 +69,17 @@ export type JSONSchemaType<T, _partial extends boolean = false> = (
6369 : T extends [ any , ...any [ ] ]
6470 ? {
6571 // JSON AnySchema for tuple
66- type : JSONType < "array" , _partial >
72+ type : JSONType < "array" , IsPartial >
6773 items : {
68- readonly [ K in keyof T ] -?: JSONSchemaType < T [ K ] > & Nullable < T [ K ] >
74+ readonly [ K in keyof T ] -?: UncheckedJSONSchemaType < T [ K ] , false > & Nullable < T [ K ] >
6975 } & { length : T [ "length" ] }
7076 minItems : T [ "length" ]
7177 } & ( { maxItems : T [ "length" ] } | { additionalItems : false } )
7278 : T extends readonly any [ ]
7379 ? {
74- type : JSONType < "array" , _partial >
75- items : JSONSchemaType < T [ 0 ] >
76- contains ?: PartialSchema < T [ 0 ] >
80+ type : JSONType < "array" , IsPartial >
81+ items : UncheckedJSONSchemaType < T [ 0 ] , false >
82+ contains ?: UncheckedPartialSchema < T [ 0 ] >
7783 minItems ?: number
7884 maxItems ?: number
7985 minContains ?: number
@@ -87,62 +93,79 @@ export type JSONSchemaType<T, _partial extends boolean = false> = (
8793 // "required" is not optional because it is often forgotten
8894 // "properties" are optional for more concise dictionary schemas
8995 // "patternProperties" and can be only used with interfaces that have string index
90- type : JSONType < "object" , _partial >
91- additionalProperties ?: boolean | JSONSchemaType < T [ string ] >
92- unevaluatedProperties ?: boolean | JSONSchemaType < T [ string ] >
93- properties ?: _partial extends true ? Partial < PropertiesSchema < T > > : PropertiesSchema < T >
94- patternProperties ?: { [ Pattern in string ] ?: JSONSchemaType < T [ string ] > }
95- propertyNames ?: Omit < JSONSchemaType < string > , "type" > & { type ?: "string" }
96- dependencies ?: { [ K in keyof T ] ?: Readonly < ( keyof T ) [ ] > | PartialSchema < T > }
96+ type : JSONType < "object" , IsPartial >
97+ additionalProperties ?: boolean | UncheckedJSONSchemaType < T [ string ] , false >
98+ unevaluatedProperties ?: boolean | UncheckedJSONSchemaType < T [ string ] , false >
99+ properties ?: IsPartial extends true
100+ ? Partial < UncheckedPropertiesSchema < T > >
101+ : UncheckedPropertiesSchema < T >
102+ patternProperties ?: { [ Pattern in string ] ?: UncheckedJSONSchemaType < T [ string ] , false > }
103+ propertyNames ?: Omit < UncheckedJSONSchemaType < string , false > , "type" > & { type ?: "string" }
104+ dependencies ?: { [ K in keyof T ] ?: Readonly < ( keyof T ) [ ] > | UncheckedPartialSchema < T > }
97105 dependentRequired ?: { [ K in keyof T ] ?: Readonly < ( keyof T ) [ ] > }
98- dependentSchemas ?: { [ K in keyof T ] ?: PartialSchema < T > }
106+ dependentSchemas ?: { [ K in keyof T ] ?: UncheckedPartialSchema < T > }
99107 minProperties ?: number
100108 maxProperties ?: number
101109 } & ( // "required" type does not guarantee that all required properties
102110 // are listed it only asserts that optional cannot be listed.
103111 // "required" is not necessary if it's a non-partial type with no required keys
104- _partial extends true
112+ IsPartial extends true
105113 ? { required : Readonly < ( keyof T ) [ ] > }
106- : [ RequiredMembers < T > ] extends [ never ]
107- ? { required ?: Readonly < RequiredMembers < T > [ ] > }
108- : { required : Readonly < RequiredMembers < T > [ ] > } )
114+ : [ UncheckedRequiredMembers < T > ] extends [ never ]
115+ ? { required ?: Readonly < UncheckedRequiredMembers < T > [ ] > }
116+ : { required : Readonly < UncheckedRequiredMembers < T > [ ] > } )
109117 : T extends null
110118 ? {
111119 nullable : true
112120 }
113121 : never ) & {
114- allOf ?: Readonly < PartialSchema < T > [ ] >
115- anyOf ?: Readonly < PartialSchema < T > [ ] >
116- oneOf ?: Readonly < PartialSchema < T > [ ] >
117- if ?: PartialSchema < T >
118- then ?: PartialSchema < T >
119- else ?: PartialSchema < T >
120- not ?: PartialSchema < T >
122+ allOf ?: Readonly < UncheckedPartialSchema < T > [ ] >
123+ anyOf ?: Readonly < UncheckedPartialSchema < T > [ ] >
124+ oneOf ?: Readonly < UncheckedPartialSchema < T > [ ] >
125+ if ?: UncheckedPartialSchema < T >
126+ then ?: UncheckedPartialSchema < T >
127+ else ?: UncheckedPartialSchema < T >
128+ not ?: UncheckedPartialSchema < T >
121129 } )
122130) & {
123131 [ keyword : string ] : any
124132 $id ?: string
125133 $ref ?: string
126134 $defs ?: {
127- [ Key in string ] ?: JSONSchemaType < Known , true >
135+ [ Key in string ] ?: UncheckedJSONSchemaType < Known , true >
128136 }
129137 definitions ?: {
130- [ Key in string ] ?: JSONSchemaType < Known , true >
138+ [ Key in string ] ?: UncheckedJSONSchemaType < Known , true >
131139 }
132140}
133141
142+ export type JSONSchemaType < T > = StrictNullChecksWrapper <
143+ "JSONSchemaType" ,
144+ UncheckedJSONSchemaType < T , false >
145+ >
146+
134147type Known = KnownRecord | [ Known , ...Known [ ] ] | Known [ ] | number | string | boolean | null
135148
136149interface KnownRecord extends Record < string , Known > { }
137150
138- export type PropertiesSchema < T > = {
139- [ K in keyof T ] -?: ( JSONSchemaType < T [ K ] > & Nullable < T [ K ] > ) | { $ref : string }
151+ type UncheckedPropertiesSchema < T > = {
152+ [ K in keyof T ] -?: ( UncheckedJSONSchemaType < T [ K ] , false > & Nullable < T [ K ] > ) | { $ref : string }
140153}
141154
142- export type RequiredMembers < T > = {
155+ export type PropertiesSchema < T > = StrictNullChecksWrapper <
156+ "PropertiesSchema" ,
157+ UncheckedPropertiesSchema < T >
158+ >
159+
160+ type UncheckedRequiredMembers < T > = {
143161 [ K in keyof T ] -?: undefined extends T [ K ] ? never : K
144162} [ keyof T ]
145163
164+ export type RequiredMembers < T > = StrictNullChecksWrapper <
165+ "RequiredMembers" ,
166+ UncheckedRequiredMembers < T >
167+ >
168+
146169type Nullable < T > = undefined extends T
147170 ? {
148171 nullable : true
0 commit comments