Skip to main content

Complex Types

One of the key features of Therefore is its support for complex data types with circular references.

Circular References

One of such data types is a circular reference. Circular references occur when an object refers to itself or to another object that refers back to the original object, forming a loop. These can be challenging to deal with in data languages, as most language does not support circular references directly.

JSON Type

An easy type that holds such a circular reference is the JSON data type. We'll provide two different methods that can be used to model such data:

./src/json1.schema.ts
export const json: ThereforeSchema = $validator(
$union([$string, $null, $boolean, $number, $record($ref(() => json)), $array($ref(() => json))]),
{
assert: false,
}
)
./src/json1.type.ts
export type Json =
| string
| null
| boolean
| number
| {
[k: string]: Json | undefined
}
| Json[]

export const Json = {
validate: require('./schemas/json1.schema.js') as ValidateFunction<Json>,
get schema() {
return Json.validate.schema
},
get errors() {
return Json.validate.errors ?? undefined
},
is: (o: unknown): o is Json => Json.validate(o) === true,
} as const
./src/json2.schema.ts
export const jsonAdv: ThereforeSchema = $validator(
$ref(() =>
$union([
$string,
$null,
$boolean,
$number,
$record($ref(() => jsonAdv)),
$array($ref(() => jsonAdv))
], {
name: 'jsonLocal',
})
)
./src/json2.type.ts
export const JsonAdv = {
validate: require('./schemas/json2.schema.js') as ValidateFunction<JsonAdv>,
get schema() {
return JsonAdv.validate.schema
},
get errors() {
return JsonAdv.validate.errors ?? undefined
},
is: (o: unknown): o is JsonAdv => JsonAdv.validate(o) === true,
assert: (o: unknown) => {
if (!JsonAdv.validate(o)) {
throw new AjvValidator.ValidationError(JsonAdv.errors ?? [])
}
},
} as const

type JsonLocal =
| string
| null
| boolean
| number
| {
[k: string]: JsonAdv | undefined
}
| JsonAdv[]