import { addIssue, BaseSchema, INVALID } from "../../core/schema/schema.js"; import type { AnySchema, ParseContext } from "../../types/common.js"; // --------------------------------------------------------------------------- // Type helpers // --------------------------------------------------------------------------- type TupleOutputs = { [K in keyof T]: T[K] extends BaseSchema ? O : never; }; // --------------------------------------------------------------------------- // TupleSchema // --------------------------------------------------------------------------- export class TupleSchema extends BaseSchema< TupleOutputs, TupleOutputs > { private readonly _schemas: T; constructor(schemas: T) { super(); this._schemas = schemas; } _parse(input: unknown, ctx: ParseContext): TupleOutputs | INVALID { if (!Array.isArray(input)) { return addIssue(ctx, { code: "VALIDATION.INVALID_TYPE", path: [...ctx.path], message: `Expected tuple (array), received ${typeof input}`, input, }); } if (input.length !== this._schemas.length) { return addIssue(ctx, { code: "VALIDATION.INVALID_TYPE", path: [...ctx.path], message: `Expected tuple of length ${this._schemas.length}, received length ${input.length}`, input, }); } const out: unknown[] = []; let hasInvalid = false; for (let i = 0; i < this._schemas.length; i++) { const schema = this._schemas[i]!; const childCtx: ParseContext = { path: [...ctx.path, i], issues: [], }; const result = schema._parse(input[i], childCtx); if (result === INVALID || childCtx.issues.length > 0) { ctx.issues.push(...childCtx.issues); hasInvalid = true; } else { out.push(result); } } return hasInvalid ? INVALID : (out as TupleOutputs); } } // --------------------------------------------------------------------------- // Factory // --------------------------------------------------------------------------- export function tuple(schemas: T): TupleSchema { return new TupleSchema(schemas); }