+/** numeric strings */
+type NumberType = "float32" | "float64" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32"
+
+/** string strings */
+type StringType = "string" | "timestamp"
+
+/** Generic JTD Schema without inference of the represented type */
+export type SomeJTDSchemaType = (
+ | // ref
+ {ref: string}
+ // primitives
+ | {type: NumberType | StringType | "boolean"}
+ // enum
+ | {enum: string[]}
+ // elements
+ | {elements: SomeJTDSchemaType}
+ // values
+ | {values: SomeJTDSchemaType}
+ // properties
+ | {
+ properties: Record<string, SomeJTDSchemaType>
+ optionalProperties?: Record<string, SomeJTDSchemaType>
+ additionalProperties?: boolean
+ }
+ | {
+ properties?: Record<string, SomeJTDSchemaType>
+ optionalProperties: Record<string, SomeJTDSchemaType>
+ additionalProperties?: boolean
+ }
+ // discriminator
+ | {discriminator: string; mapping: Record<string, SomeJTDSchemaType>}
+ // empty
+ // NOTE see the end of
+ // https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492
+ // eslint-disable-next-line @typescript-eslint/ban-types
+ | {}
+) & {
+ nullable?: boolean
+ metadata?: Record<string, unknown>
+ definitions?: Record<string, SomeJTDSchemaType>
+}
+
/** required keys of an object, not undefined */
type RequiredKeys<T> = {
[K in keyof T]-?: undefined extends T[K] ? never : K
: true
: false
-/** numeric strings */
-type NumberType = "float32" | "float64" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32"
-
-/** string strings */
-type StringType = "string" | "timestamp"
-
/** actual schema */
export type JTDSchemaType<T, D extends Record<string, unknown> = Record<string, never>> = (
| // refs - where null wasn't specified, must match exactly
true extends IsValues<T>
? T extends Record<string, infer V>
? {
- values: JTDSchemaType<V>
+ values: JTDSchemaType<V, D>
}
: never
: // properties
type JTDDataDef<S, D extends Record<string, unknown>> =
| (// ref
S extends {ref: string}
- ? JTDDataDef<D[S["ref"]], D>
+ ? D extends {[K in S["ref"]]: infer V}
+ ? JTDDataDef<V, D>
+ : never
: // type
S extends {type: NumberType}
? number
+ : S extends {type: "boolean"}
+ ? boolean
: S extends {type: "string"}
? string
: S extends {type: "timestamp"}
optionalProperties?: Record<string, unknown>
additionalProperties?: boolean
}
- ? {-readonly [K in keyof S["properties"]]-?: JTDDataDef<S["properties"][K], D>} &
- {
- -readonly [K in keyof S["optionalProperties"]]+?: JTDDataDef<
- S["optionalProperties"][K],
- D
- >
- } &
- ([S["additionalProperties"]] extends [true] ? Record<string, unknown> : unknown)
+ ? {-readonly [K in keyof S["properties"]]-?: JTDDataDef<S["properties"][K], D>} & {
+ -readonly [K in keyof S["optionalProperties"]]+?: JTDDataDef<
+ S["optionalProperties"][K],
+ D
+ >
+ } & ([S["additionalProperties"]] extends [true] ? Record<string, unknown> : unknown)
: S extends {
properties?: Record<string, unknown>
optionalProperties: Record<string, unknown>
additionalProperties?: boolean
}
- ? {-readonly [K in keyof S["properties"]]-?: JTDDataDef<S["properties"][K], D>} &
- {
- -readonly [K in keyof S["optionalProperties"]]+?: JTDDataDef<
- S["optionalProperties"][K],
- D
- >
- } &
- ([S["additionalProperties"]] extends [true] ? Record<string, unknown> : unknown)
+ ? {-readonly [K in keyof S["properties"]]-?: JTDDataDef<S["properties"][K], D>} & {
+ -readonly [K in keyof S["optionalProperties"]]+?: JTDDataDef<
+ S["optionalProperties"][K],
+ D
+ >
+ } & ([S["additionalProperties"]] extends [true] ? Record<string, unknown> : unknown)
: // values
S extends {values: infer V}
? Record<string, JTDDataDef<V, D>>