import type { Definition, DefinitionType, PrimitiveType, RawPrimitiveType } from "../annotations.js"; import type { Schema } from "../Schema.js"; import type { ArraySchema } from "./custom/ArraySchema.js"; import type { CollectionSchema } from "./custom/CollectionSchema.js"; import type { MapSchema } from "./custom/MapSchema.js"; import type { SetSchema } from "./custom/SetSchema.js"; export type Constructor = new (...args: any[]) => T; // Helper to convert primitive type literals to actual runtime types type PrimitiveStringToType = T extends "string" ? string : T extends "number" | "int8" | "uint8" | "int16" | "uint16" | "int32" | "uint32" | "int64" | "uint64" | "float32" | "float64" ? number : T extends "boolean" ? boolean : T; export interface Collection { [Symbol.iterator](): IterableIterator; forEach(callback: Function): void; entries(): IterableIterator<[K, V]>; } export type InferValueType = T extends "string" ? string : T extends "number" ? number : T extends "int8" ? number : T extends "uint8" ? number : T extends "int16" ? number : T extends "uint16" ? number : T extends "int32" ? number : T extends "uint32" ? number : T extends "int64" ? number : T extends "uint64" ? number : T extends "float32" ? number : T extends "float64" ? number : T extends "boolean" ? boolean // Handle { type: ... } patterns : T extends { type: infer ChildType extends PrimitiveType } ? InferValueType : T extends { type: infer ChildType extends Constructor } ? InstanceType : T extends { type: Array } ? (ChildType extends Record ? ChildType[keyof ChildType][] : ChildType[]) // TS ENUM : T extends { type: { map: infer ChildType } } ? (ChildType extends Record ? MapSchema : MapSchema) // TS ENUM : T extends { type: { set: infer ChildType } } ? (ChildType extends Record ? SetSchema : SetSchema) // TS ENUM : T extends { type: { collection: infer ChildType } } ? (ChildType extends Record ? CollectionSchema : CollectionSchema) // TS ENUM : T extends { type: infer ChildType } ? (ChildType extends Record ? ChildType[keyof ChildType] : ChildType) // TS ENUM // Handle direct array patterns : T extends Array ? ArraySchema> : T extends Array ? (ChildType extends Record ? ArraySchema : ArraySchema>) // TS ENUM // Handle collection object patterns : T extends { array: infer ChildType extends Constructor } ? ArraySchema> : T extends { array: infer ChildType } ? (ChildType extends Record ? ArraySchema : ArraySchema>) // TS ENUM : T extends { map: infer ChildType extends Constructor } ? MapSchema> : T extends { map: infer ChildType } ? (ChildType extends Record ? MapSchema : MapSchema>) // TS ENUM : T extends { set: infer ChildType extends Constructor } ? SetSchema> : T extends { set: infer ChildType extends RawPrimitiveType } ? SetSchema> // primitive types : T extends { set: infer ChildType } ? (ChildType extends Record ? SetSchema : SetSchema) // TS ENUM : T extends { collection: infer ChildType extends Constructor } ? CollectionSchema> : T extends { collection: infer ChildType extends RawPrimitiveType } ? CollectionSchema> // primitive types : T extends { collection: infer ChildType } ? (ChildType extends Record ? CollectionSchema : CollectionSchema) // TS ENUM // Handle direct types : T extends Constructor ? InstanceType : T extends Record ? T[keyof T] // TS ENUM : T extends PrimitiveType ? T : never; export type InferSchemaInstanceType = { [K in keyof T]: T[K] extends (...args: any[]) => any ? (T[K] extends new (...args: any[]) => any ? InferValueType : T[K]) : InferValueType } & Schema; export type NonFunctionProps = Omit; export type NonFunctionPropNames = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; export type NonFunctionNonPrimitivePropNames = { [K in keyof T]: T[K] extends Function ? never : T[K] extends number | string | boolean ? never : K }[keyof T]; // Helper to recursively convert Schema instances to their JSON representation type ToJSONValue = U extends Schema ? ToJSON : PrimitiveStringToType; export type ToJSON = { [K in keyof T as T[K] extends Function ? never : K]: T[K] extends MapSchema ? Record> : T[K] extends Map ? Record> : T[K] extends ArraySchema ? ToJSONValue[] : T[K] extends SetSchema ? ToJSONValue[] : T[K] extends CollectionSchema ? ToJSONValue[] : T[K] extends Schema ? ToJSON : T[K] }; // Helper type to check if T is exactly 'never' (meaning no InitProps was provided) export type IsNever = [T] extends [never] ? true : false; /** * Type helper for .assign() method - allows assigning values in a flexible way * - Primitives can be assigned directly * - Schema instances can be assigned from plain objects or Schema instances * - Collections can be assigned from their JSON representations */ export type AssignableProps = { [K in NonFunctionPropNames]?: T[K] extends MapSchema ? MapSchema | Record) : U> : T[K] extends ArraySchema ? ArraySchema | (U extends Schema ? (U | AssignableProps)[] : U[]) : T[K] extends SetSchema ? SetSchema | Set | (U extends Schema ? (U | AssignableProps)[] : U[]) : T[K] extends CollectionSchema ? CollectionSchema | (U extends Schema ? (U | AssignableProps)[] : U[]) : T[K] extends Schema ? T[K] | AssignableProps : T[K] };