@oh-my-pi/omptype 17.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/typebox.ts ADDED
@@ -0,0 +1,487 @@
1
+ import { OmpTypeError } from "./errors";
2
+ import type { Def } from "./ir";
3
+ import { type NarrowContext, type Type as OmpType, type } from "./type";
4
+
5
+ export interface Meta {
6
+ title?: string;
7
+ description?: string;
8
+ default?: unknown;
9
+ examples?: unknown[];
10
+ [key: string]: unknown;
11
+ }
12
+
13
+ export interface StringOpts extends Meta {
14
+ minLength?: number;
15
+ maxLength?: number;
16
+ pattern?: string;
17
+ format?: string;
18
+ }
19
+
20
+ export interface NumberOpts extends Meta {
21
+ minimum?: number;
22
+ maximum?: number;
23
+ exclusiveMinimum?: number;
24
+ exclusiveMaximum?: number;
25
+ multipleOf?: number;
26
+ }
27
+
28
+ export interface ArrayOpts extends Meta {
29
+ minItems?: number;
30
+ maxItems?: number;
31
+ uniqueItems?: boolean;
32
+ }
33
+
34
+ export interface ObjectOpts extends Meta {
35
+ additionalProperties?: boolean | TSchema;
36
+ }
37
+ const OPTIONAL_INNER = Symbol("omptype.typebox.optionalInner");
38
+ const OBJECT_INFO = Symbol("omptype.typebox.objectInfo");
39
+
40
+ export interface TypeBoxValidationFailure {
41
+ message: string;
42
+ }
43
+
44
+ export type TypeBoxSafeParseResult<T> =
45
+ | { success: true; data: T }
46
+ | { success: false; error: TypeBoxValidationFailure };
47
+
48
+ interface LegacyTypeBoxCompat<T> {
49
+ /** TypeBox compatibility validator used by legacy extension loaders. */
50
+ __validator(data: unknown): T | TypeBoxValidationFailure;
51
+ /** Zod-style compatibility parser used by legacy extensions. */
52
+ safeParse(input: unknown): TypeBoxSafeParseResult<T>;
53
+ }
54
+
55
+ export type TSchema<T = unknown> = OmpType<T> & LegacyTypeBoxCompat<T>;
56
+ export type Static<T extends TSchema> = T["infer"];
57
+ export type TAny = TSchema<unknown>;
58
+ export type TUnknown = TSchema<unknown>;
59
+ export type TNever = TSchema<never>;
60
+ export type TNull = TSchema<null>;
61
+ export type TString = TSchema<string>;
62
+ export type TNumber = TSchema<number>;
63
+ export type TInteger = TSchema<number>;
64
+ export type TBoolean = TSchema<boolean>;
65
+ export type TLiteral<V extends string | number | boolean | null> = TSchema<V>;
66
+ export type TArray<E extends TSchema> = TSchema<Static<E>[]>;
67
+ export type TTuple<E extends readonly TSchema[] = readonly TSchema[]> = TSchema<{
68
+ -readonly [K in keyof E]: Static<E[K]>;
69
+ }>;
70
+ export type TOptional<E extends TSchema> = TSchema<Static<E> | undefined> & { readonly [OPTIONAL_INNER]: E };
71
+ export type TUnion<E extends readonly TSchema[] = readonly TSchema[]> = TSchema<Static<E[number]>>;
72
+ export type TIntersect<E extends readonly TSchema[] = readonly TSchema[]> = TSchema<
73
+ UnionToIntersection<Static<E[number]>>
74
+ >;
75
+ export type TEnum<E extends readonly (string | number)[] = readonly (string | number)[]> = TSchema<E[number]>;
76
+ export type TRecord<K extends TSchema, V extends TSchema> = TSchema<Record<Extract<Static<K>, PropertyKey>, Static<V>>>;
77
+ export type TNullable<E extends TSchema> = TSchema<Static<E> | null>;
78
+ export type TReadonly<E extends TSchema> = TSchema<Readonly<Static<E>>>;
79
+ export type TUnsafe<T = unknown> = TSchema<T>;
80
+
81
+ type OptionalKeys<P extends Record<string, TSchema>> = {
82
+ [K in keyof P]-?: P[K] extends { readonly [OPTIONAL_INNER]: TSchema } ? K : never;
83
+ }[keyof P];
84
+ type RequiredKeys<P extends Record<string, TSchema>> = Exclude<keyof P, OptionalKeys<P>>;
85
+ type ObjectStatic<P extends Record<string, TSchema>> = {
86
+ [K in RequiredKeys<P>]: Static<P[K]>;
87
+ } & {
88
+ [K in OptionalKeys<P>]?: Exclude<Static<P[K]>, undefined>;
89
+ };
90
+ export type TObject<P extends Record<string, TSchema> = Record<string, TSchema>> = TSchema<ObjectStatic<P>>;
91
+ type RequiredProps<P extends Record<string, TSchema>> = {
92
+ [K in keyof P]: P[K] extends TOptional<infer E> ? E : P[K];
93
+ };
94
+
95
+ interface RuntimeType<T> extends OmpType<T> {
96
+ [OPTIONAL_INNER]?: TSchema;
97
+ [OBJECT_INFO]?: ObjectInfo;
98
+ describe(description: string): RuntimeType<T>;
99
+ default(value: T | (() => T)): RuntimeType<T>;
100
+ or<R>(schema: OmpType<R>): RuntimeType<T | R>;
101
+ and<R>(schema: OmpType<R>): RuntimeType<T & R>;
102
+ array(): RuntimeType<T[]>;
103
+ atLeastLength(bound: number): RuntimeType<T>;
104
+ atMostLength(bound: number): RuntimeType<T>;
105
+ atLeast(bound: number): RuntimeType<T>;
106
+ atMost(bound: number): RuntimeType<T>;
107
+ narrow<N extends T>(predicate: (value: T, ctx: NarrowContext) => value is N): RuntimeType<N>;
108
+ narrow(predicate: (value: T, ctx: NarrowContext) => boolean): RuntimeType<T>;
109
+ }
110
+ type CompatRuntime<T> = RuntimeType<T> & LegacyTypeBoxCompat<T>;
111
+
112
+ type ObjectInfo = { props: Record<string, TSchema>; additionalProperties?: boolean | TSchema };
113
+
114
+ function validationFailure(message: string): TypeBoxValidationFailure {
115
+ return { message };
116
+ }
117
+
118
+ function withLegacyCompat<T>(schema: OmpType<T>): CompatRuntime<T> {
119
+ const compatSchema = schema as unknown as CompatRuntime<T>;
120
+ if (!Object.hasOwn(compatSchema, "__validator")) {
121
+ Object.defineProperty(compatSchema, "__validator", {
122
+ value: (data: unknown): T | TypeBoxValidationFailure => {
123
+ const result = schema(data);
124
+ return result instanceof type.errors ? validationFailure(result.summary) : result;
125
+ },
126
+ configurable: true,
127
+ });
128
+ }
129
+ if (!Object.hasOwn(compatSchema, "safeParse")) {
130
+ Object.defineProperty(compatSchema, "safeParse", {
131
+ value: (input: unknown): TypeBoxSafeParseResult<T> => {
132
+ const result = schema(input);
133
+ return result instanceof type.errors
134
+ ? { success: false, error: validationFailure(result.summary) }
135
+ : { success: true, data: result };
136
+ },
137
+ configurable: true,
138
+ });
139
+ }
140
+ return compatSchema;
141
+ }
142
+
143
+ function applyMeta<T>(schema: RuntimeType<T>, opts?: Meta): CompatRuntime<T> {
144
+ let result = schema;
145
+ const description = opts?.description ?? opts?.title;
146
+ if (description !== undefined) result = result.describe(description);
147
+ if (opts && Object.hasOwn(opts, "default")) result = result.default(opts.default as T);
148
+ return withLegacyCompat(result);
149
+ }
150
+
151
+ function withJsonSchemaKeywords<T>(schema: CompatRuntime<T>, keywords: Record<string, unknown>): CompatRuntime<T> {
152
+ const emitBase = schema.toJsonSchema;
153
+ schema.toJsonSchema = options => ({ ...emitBase(options), ...keywords });
154
+ return schema;
155
+ }
156
+
157
+ function checkFiniteOption(name: string, value: number | undefined): void {
158
+ if (value !== undefined && !Number.isFinite(value)) throw new OmpTypeError(`${name} must be finite`);
159
+ }
160
+
161
+ function tString(opts?: StringOpts): TString {
162
+ checkFiniteOption("minLength", opts?.minLength);
163
+ checkFiniteOption("maxLength", opts?.maxLength);
164
+ let schema = type.raw(
165
+ opts?.format === "url" || opts?.format === "uri" ? "string.url" : "string",
166
+ ) as RuntimeType<string>;
167
+ if (opts?.minLength !== undefined) schema = schema.atLeastLength(opts.minLength);
168
+ if (opts?.maxLength !== undefined) schema = schema.atMostLength(opts.maxLength);
169
+ if (opts?.pattern !== undefined) {
170
+ let regex: RegExp;
171
+ try {
172
+ regex = new RegExp(opts.pattern);
173
+ } catch {
174
+ throw new OmpTypeError(`invalid regular expression pattern ${JSON.stringify(opts.pattern)}`);
175
+ }
176
+ schema = schema.narrow((value, ctx) => regex.test(value) || ctx.mustBe(`a string matching ${opts.pattern}`));
177
+ }
178
+ if (opts?.format !== undefined && opts.format !== "url" && opts.format !== "uri") {
179
+ const format = opts.format;
180
+ const valid = formatPredicate(format);
181
+ schema = schema.narrow((value, ctx) => valid(value) || ctx.mustBe(`a string in ${format} format`));
182
+ }
183
+ return applyMeta(schema, opts);
184
+ }
185
+
186
+ function formatPredicate(format: string): (value: string) => boolean {
187
+ switch (format) {
188
+ case "url":
189
+ case "uri":
190
+ return value => {
191
+ try {
192
+ new URL(value);
193
+ return true;
194
+ } catch {
195
+ return false;
196
+ }
197
+ };
198
+ case "email":
199
+ return value => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
200
+ case "uuid":
201
+ return value => /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
202
+ case "date-time":
203
+ return value =>
204
+ /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?(?:Z|[+-]\d\d:\d\d)$/.test(value) &&
205
+ !Number.isNaN(Date.parse(value));
206
+ case "date":
207
+ return value => /^\d{4}-\d\d-\d\d$/.test(value) && !Number.isNaN(Date.parse(`${value}T00:00:00Z`));
208
+ default:
209
+ return () => true;
210
+ }
211
+ }
212
+
213
+ function tNumber(opts?: NumberOpts, integer = false): TNumber {
214
+ for (const key of ["minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum", "multipleOf"] as const) {
215
+ checkFiniteOption(key, opts?.[key]);
216
+ }
217
+ if (opts?.multipleOf !== undefined && opts.multipleOf <= 0)
218
+ throw new OmpTypeError("multipleOf must be greater than zero");
219
+ let lower: { value: number; exclusive: boolean } | undefined;
220
+ if (opts?.minimum !== undefined) lower = { value: opts.minimum, exclusive: false };
221
+ if (opts?.exclusiveMinimum !== undefined && (!lower || opts.exclusiveMinimum >= lower.value)) {
222
+ lower = { value: opts.exclusiveMinimum, exclusive: true };
223
+ }
224
+ let upper: { value: number; exclusive: boolean } | undefined;
225
+ if (opts?.maximum !== undefined) upper = { value: opts.maximum, exclusive: false };
226
+ if (opts?.exclusiveMaximum !== undefined && (!upper || opts.exclusiveMaximum <= upper.value)) {
227
+ upper = { value: opts.exclusiveMaximum, exclusive: true };
228
+ }
229
+ const keyword = integer ? "number.integer" : "number";
230
+ const lowerDsl = lower ? `${lower.value} ${lower.exclusive ? "<" : "<="} ` : "";
231
+ const upperDsl = upper ? ` ${upper.exclusive ? "<" : "<="} ${upper.value}` : "";
232
+ let schema = type.raw(`${lowerDsl}${keyword}${upperDsl}`) as RuntimeType<number>;
233
+ if (opts?.multipleOf !== undefined) {
234
+ const divisor = opts.multipleOf;
235
+ schema = schema.narrow((value, ctx) => {
236
+ const quotient = value / divisor;
237
+ return (
238
+ Math.abs(quotient - Math.round(quotient)) <= Number.EPSILON * Math.max(1, Math.abs(quotient)) ||
239
+ ctx.mustBe(`a multiple of ${divisor}`)
240
+ );
241
+ });
242
+ }
243
+ return applyMeta(schema, opts);
244
+ }
245
+
246
+ function tLiteral<const V extends string | number | boolean | null>(value: V, opts?: Meta): TLiteral<V> {
247
+ return applyMeta(type.enumerated(value) as RuntimeType<V>, opts);
248
+ }
249
+
250
+ function tNever(opts?: Meta): TNever {
251
+ return applyMeta(
252
+ (type.raw("unknown") as RuntimeType<unknown>).narrow((_value, ctx): _value is never => ctx.mustBe("never")),
253
+ opts,
254
+ );
255
+ }
256
+
257
+ function tUnion<const E extends readonly TSchema[]>(schemas: E, opts?: Meta): TUnion<E> {
258
+ if (schemas.length === 0) return tNever(opts) as TUnion<E>;
259
+ let result = schemas[0] as unknown as RuntimeType<unknown>;
260
+ for (let i = 1; i < schemas.length; i++) result = result.or(schemas[i]);
261
+ return applyMeta(result, opts) as TUnion<E>;
262
+ }
263
+
264
+ function tIntersect<const E extends readonly TSchema[]>(
265
+ schemas: E,
266
+ opts?: Meta,
267
+ ): TSchema<UnionToIntersection<Static<E[number]>>> {
268
+ if (schemas.length === 0)
269
+ return applyMeta(type.raw("unknown") as RuntimeType<unknown>, opts) as TSchema<
270
+ UnionToIntersection<Static<E[number]>>
271
+ >;
272
+ const validateAll = (): RuntimeType<UnionToIntersection<Static<E[number]>>> => {
273
+ const base = type.raw("unknown") as RuntimeType<unknown>;
274
+ return base.narrow((value, ctx): value is UnionToIntersection<Static<E[number]>> => {
275
+ for (const schema of schemas) {
276
+ if (schema(value) instanceof type.errors) return ctx.mustBe("a value satisfying every intersection member");
277
+ }
278
+ return true;
279
+ });
280
+ };
281
+ if (schemas.some(schema => schema.hasSteps)) return applyMeta(validateAll(), opts);
282
+ let result = schemas[0] as unknown as RuntimeType<unknown>;
283
+ try {
284
+ for (let i = 1; i < schemas.length; i++) result = result.and(schemas[i]);
285
+ } catch (error) {
286
+ if (error instanceof OmpTypeError) return applyMeta(validateAll(), opts);
287
+ throw error;
288
+ }
289
+ return applyMeta(result, opts) as TSchema<UnionToIntersection<Static<E[number]>>>;
290
+ }
291
+ type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void
292
+ ? I
293
+ : never;
294
+
295
+ function enumValues(values: Record<string, string | number> | readonly (string | number)[]): (string | number)[] {
296
+ if (Array.isArray(values)) return [...values];
297
+ const result: (string | number)[] = [];
298
+ const record = values as Record<string, string | number>;
299
+ for (const key in record) {
300
+ const value = record[key];
301
+ if (!(/^\d+$/.test(key) && typeof value === "string") && !result.includes(value)) result.push(value);
302
+ }
303
+ return result;
304
+ }
305
+
306
+ function tEnum<const E extends Record<string, string | number> | readonly (string | number)[]>(
307
+ values: E,
308
+ opts?: Meta,
309
+ ): TSchema<E extends readonly (infer V)[] ? V : E[keyof E]> {
310
+ return applyMeta(type.enumerated(...enumValues(values)) as RuntimeType<string | number>, opts) as unknown as TSchema<
311
+ E extends readonly (infer V)[] ? V : E[keyof E]
312
+ >;
313
+ }
314
+
315
+ function tArray<E extends TSchema>(item: E, opts?: ArrayOpts): TArray<E> {
316
+ checkFiniteOption("minItems", opts?.minItems);
317
+ checkFiniteOption("maxItems", opts?.maxItems);
318
+ let schema = (item as unknown as RuntimeType<Static<E>>).array();
319
+ if (opts?.minItems !== undefined) schema = schema.atLeastLength(opts.minItems);
320
+ if (opts?.maxItems !== undefined) schema = schema.atMostLength(opts.maxItems);
321
+ if (opts?.uniqueItems) {
322
+ schema = schema.narrow((values, ctx) => {
323
+ for (let i = 0; i < values.length; i++) {
324
+ for (let j = i + 1; j < values.length; j++) {
325
+ if (jsonEqual(values[i], values[j])) return ctx.mustBe("an array with unique items");
326
+ }
327
+ }
328
+ return true;
329
+ });
330
+ }
331
+ const result = applyMeta(schema, opts);
332
+ return opts?.uniqueItems ? withJsonSchemaKeywords(result, { uniqueItems: true }) : result;
333
+ }
334
+
335
+ function jsonEqual(left: unknown, right: unknown): boolean {
336
+ if (Object.is(left, right)) return true;
337
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
338
+ try {
339
+ return JSON.stringify(left) === JSON.stringify(right);
340
+ } catch {
341
+ return false;
342
+ }
343
+ }
344
+
345
+ function tTuple<const E extends readonly TSchema[]>(items: E, opts?: Meta): TTuple<E> {
346
+ const schema = (type.raw("unknown") as RuntimeType<unknown>).narrow(
347
+ (value, ctx): value is { -readonly [K in keyof E]: Static<E[K]> } => {
348
+ if (!Array.isArray(value) || value.length !== items.length)
349
+ return ctx.mustBe(`a tuple of length ${items.length}`);
350
+ for (let i = 0; i < items.length; i++)
351
+ if (items[i](value[i]) instanceof type.errors) return ctx.mustBe(`a valid item at index ${i}`);
352
+ return true;
353
+ },
354
+ );
355
+ return applyMeta(schema, opts);
356
+ }
357
+
358
+ function tObject<const P extends Record<string, TSchema>>(properties: P, opts?: ObjectOpts): TObject<P> {
359
+ const def: Record<string, Def> = {};
360
+ const props: Record<string, TSchema> = {};
361
+ for (const key in properties) {
362
+ const schema = properties[key];
363
+ const inner = (schema as unknown as RuntimeType<unknown>)[OPTIONAL_INNER];
364
+ def[inner ? `${key}?` : key] = (inner ?? schema) as Def;
365
+ props[key] = schema;
366
+ }
367
+ if (opts?.additionalProperties === false) def["+"] = "reject";
368
+ else if (opts?.additionalProperties && opts.additionalProperties !== true)
369
+ def["[string]"] = opts.additionalProperties as Def;
370
+ const schema = applyMeta(type.raw(def) as RuntimeType<ObjectStatic<P>>, opts);
371
+ schema[OBJECT_INFO] = { props, additionalProperties: opts?.additionalProperties };
372
+ return schema;
373
+ }
374
+
375
+ function tRecord<K extends TSchema, V extends TSchema>(key: K, value: V, opts?: Meta): TRecord<K, V> {
376
+ const base = (type.raw({ "[string]": value }) as RuntimeType<Record<string, Static<V>>>).narrow((record, ctx) => {
377
+ for (const name in record)
378
+ if (key(name) instanceof type.errors) return ctx.mustBe("an object with valid record keys");
379
+ return true;
380
+ });
381
+ return applyMeta(base, opts) as TRecord<K, V>;
382
+ }
383
+
384
+ function tOptional<E extends TSchema>(schema: E, opts?: Meta): TOptional<E> {
385
+ const marker = applyMeta(
386
+ (schema as unknown as RuntimeType<Static<E>>).or(type.raw("undefined")),
387
+ opts,
388
+ ) as RuntimeType<Static<E> | undefined>;
389
+ marker[OPTIONAL_INNER] = schema;
390
+ return marker as unknown as TOptional<E>;
391
+ }
392
+
393
+ function tNullable<E extends TSchema>(schema: E, opts?: Meta): TSchema<Static<E> | null> {
394
+ return applyMeta((schema as unknown as RuntimeType<Static<E>>).or(type.raw("null")), opts);
395
+ }
396
+
397
+ function requireObject(schema: TSchema, operation: string): ObjectInfo {
398
+ const info = (schema as unknown as RuntimeType<unknown>)[OBJECT_INFO];
399
+ if (!info) throw new OmpTypeError(`Type.${operation} requires a schema created by Type.Object`);
400
+ return info;
401
+ }
402
+
403
+ function tPartial<P extends Record<string, TSchema>>(schema: TObject<P>): TSchema<Partial<ObjectStatic<P>>> {
404
+ const info = requireObject(schema, "Partial");
405
+ const props: Record<string, TSchema> = {};
406
+ for (const key in info.props)
407
+ props[key] = (info.props[key] as unknown as RuntimeType<unknown>)[OPTIONAL_INNER]
408
+ ? info.props[key]
409
+ : tOptional(info.props[key]);
410
+ return tObject(props, { additionalProperties: info.additionalProperties }) as TSchema<Partial<ObjectStatic<P>>>;
411
+ }
412
+
413
+ function tRequired<P extends Record<string, TSchema>>(schema: TObject<P>): TObject<RequiredProps<P>> {
414
+ const info = requireObject(schema, "Required");
415
+ const props: Record<string, TSchema> = {};
416
+ for (const key in info.props) {
417
+ props[key] = (info.props[key] as unknown as RuntimeType<unknown>)[OPTIONAL_INNER] ?? info.props[key];
418
+ }
419
+ return tObject(props, { additionalProperties: info.additionalProperties }) as TObject<RequiredProps<P>>;
420
+ }
421
+
422
+ function tPick<P extends Record<string, TSchema>, const K extends readonly (keyof P)[]>(
423
+ schema: TObject<P>,
424
+ keys: K,
425
+ ): TObject<Pick<P, K[number]>> {
426
+ const info = requireObject(schema, "Pick");
427
+ const props: Record<string, TSchema> = {};
428
+ for (const key of keys) if (typeof key === "string" && info.props[key]) props[key] = info.props[key];
429
+ return tObject(props, { additionalProperties: info.additionalProperties }) as TObject<Pick<P, K[number]>>;
430
+ }
431
+
432
+ function tOmit<P extends Record<string, TSchema>, const K extends readonly (keyof P)[]>(
433
+ schema: TObject<P>,
434
+ keys: K,
435
+ ): TObject<Omit<P, K[number]>> {
436
+ const info = requireObject(schema, "Omit");
437
+ const omitted = new Set<PropertyKey>(keys);
438
+ const props: Record<string, TSchema> = {};
439
+ for (const key in info.props) if (!omitted.has(key)) props[key] = info.props[key];
440
+ return tObject(props, { additionalProperties: info.additionalProperties }) as TObject<Omit<P, K[number]>>;
441
+ }
442
+
443
+ function tComposite<const E extends readonly TObject<Record<string, TSchema>>[]>(
444
+ schemas: E,
445
+ opts?: ObjectOpts,
446
+ ): TSchema<UnionToIntersection<Static<E[number]>>> {
447
+ const props: Record<string, TSchema> = {};
448
+ for (const schema of schemas) Object.assign(props, requireObject(schema, "Composite").props);
449
+ return tObject(props, opts) as TSchema<UnionToIntersection<Static<E[number]>>>;
450
+ }
451
+
452
+ function tUnsafe<T = unknown>(_jsonSchema: Record<string, unknown> = {}): TUnsafe<T> {
453
+ // Raw JSON Schema is accepted for source compatibility but is not retained or validated:
454
+ // omptype cannot honestly implement that contract without importing a second validator.
455
+ return withLegacyCompat(type.unknown as OmpType<T>);
456
+ }
457
+
458
+ export const Type = {
459
+ String: tString,
460
+ Number: (opts?: NumberOpts) => tNumber(opts),
461
+ Integer: (opts?: NumberOpts) => tNumber(opts, true),
462
+ Boolean: (opts?: Meta) => applyMeta(type.raw("boolean") as RuntimeType<boolean>, opts),
463
+ Null: (opts?: Meta) => applyMeta(type.raw("null") as RuntimeType<null>, opts),
464
+ Any: (opts?: Meta) => applyMeta(type.raw("unknown") as RuntimeType<unknown>, opts),
465
+ Unknown: (opts?: Meta) => applyMeta(type.raw("unknown") as RuntimeType<unknown>, opts),
466
+ Never: tNever,
467
+ Literal: tLiteral,
468
+ Union: tUnion,
469
+ Intersect: tIntersect,
470
+ Enum: tEnum,
471
+ Array: tArray,
472
+ Tuple: tTuple,
473
+ Object: tObject,
474
+ Record: tRecord,
475
+ Optional: tOptional,
476
+ Nullable: tNullable,
477
+ Readonly: <E extends TSchema>(schema: E): E => withLegacyCompat(schema) as unknown as E,
478
+ Partial: tPartial,
479
+ Required: tRequired,
480
+ Pick: tPick,
481
+ Omit: tOmit,
482
+ Composite: tComposite,
483
+ Unsafe: tUnsafe,
484
+ } as const;
485
+
486
+ export type TypeBuilder = typeof Type;
487
+ export default { Type };