zod
Version:
TypeScript-first schema declaration and validation library with static type inference
144 lines (126 loc) • 5.17 kB
text/typescript
import { _tuple } from "./api.js";
import { parse, parseAsync } from "./parse.js";
import * as schemas from "./schemas.js";
import { $ZodTuple } from "./schemas.js";
import type * as util from "./util.js";
//////////////////////////////////////////
//////////////////////////////////////////
////////// //////////
////////// $ZodFunction //////////
////////// //////////
//////////////////////////////////////////
//////////////////////////////////////////
export interface $ZodFunctionDef /* extends schemas.$ZodTypeDef */ {
type: "function";
input: $ZodFunctionArgs | null;
output: schemas.$ZodType | null;
}
export type $ZodFunctionArgs = schemas.$ZodType<unknown[], unknown[]>;
export type $InferInnerFunctionType<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
...args: Args["_zod"]["output"]
) => Returns["_zod"]["input"];
export type $InferInnerFunctionTypeAsync<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
...args: Args["_zod"]["output"]
) => util.MaybeAsync<Returns["_zod"]["input"]>;
export type $InferOuterFunctionType<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
...args: Args["_zod"]["input"]
) => Returns["_zod"]["output"];
export type $InferOuterFunctionTypeAsync<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
...args: Args["_zod"]["input"]
) => util.MaybeAsync<Returns["_zod"]["output"]>;
export class $ZodFunction<
Args extends $ZodFunctionArgs = $ZodFunctionArgs,
Returns extends schemas.$ZodType = schemas.$ZodType,
> {
_def: $ZodFunctionDef;
_input!: $InferInnerFunctionType<Args, Returns>;
_output!: $InferOuterFunctionType<Args, Returns>;
constructor(def: $ZodFunctionDef) {
this._def = def;
}
implement<F extends $InferInnerFunctionType<Args, Returns>>(
func: F
): F extends this["_output"] ? F : this["_output"] {
if (typeof func !== "function") {
throw new Error("implement() must be called with a function");
}
const impl = ((...args: any[]) => {
const parsedArgs = this._def.input ? parse(this._def.input, args, undefined, { callee: impl }) : args;
if (!Array.isArray(parsedArgs)) {
throw new Error("Invalid arguments schema: not an array or tuple schema.");
}
const output = func(...parsedArgs);
return this._def.output ? parse(this._def.output, output, undefined, { callee: impl }) : output;
}) as any;
return impl;
}
implementAsync<F extends $InferInnerFunctionTypeAsync<Args, Returns>>(
func: F
): F extends $InferOuterFunctionTypeAsync<Args, Returns> ? F : $InferOuterFunctionTypeAsync<Args, Returns> {
if (typeof func !== "function") {
throw new Error("implement() must be called with a function");
}
const impl = (async (...args: any[]) => {
const parsedArgs = this._def.input ? await parseAsync(this._def.input, args, undefined, { callee: impl }) : args;
if (!Array.isArray(parsedArgs)) {
throw new Error("Invalid arguments schema: not an array or tuple schema.");
}
const output = await func(...parsedArgs);
return this._def.output ? parseAsync(this._def.output, output, undefined, { callee: impl }) : output;
}) as any;
return impl;
}
input<const Items extends util.TupleItems, const Rest extends schemas.$ZodType | null = null>(
args: Items,
rest?: Rest
): $ZodFunction<schemas.$ZodTuple<Items, Rest>, Returns>;
input<NewArgs extends $ZodFunctionArgs>(args: NewArgs): $ZodFunction<NewArgs, Returns>;
input(...args: any[]): $ZodFunction<any, Returns> {
if (Array.isArray(args[0])) {
return new $ZodFunction({
type: "function",
input: new $ZodTuple({
type: "tuple",
items: args[0],
rest: args[1],
}),
output: this._def.output,
});
}
return new $ZodFunction({
type: "function",
input: args[0],
output: this._def.output,
});
}
output<NewReturns extends schemas.$ZodType>(output: NewReturns): $ZodFunction<Args, NewReturns> {
return new $ZodFunction({
type: "function",
input: this._def.input,
output,
});
}
}
export interface $ZodFunctionParams<I extends $ZodFunctionArgs, O extends schemas.$ZodType> {
input?: I;
output?: O;
}
function _function(): $ZodFunction;
function _function<
const In extends Array<schemas.$ZodType> = Array<schemas.$ZodType>,
Out extends schemas.$ZodType = schemas.$ZodType,
>(params?: { input?: In; output?: Out }): $ZodFunction<$ZodTuple<In, null>, Out>;
function _function<In extends $ZodFunctionArgs = $ZodFunctionArgs, Out extends schemas.$ZodType = schemas.$ZodType>(
params?: $ZodFunctionParams<In, Out>
): $ZodFunction<In, Out>;
function _function(params?: {
output?: schemas.$ZodType;
input?: $ZodFunctionArgs | Array<schemas.$ZodType>;
}): any {
return new $ZodFunction({
type: "function",
input: Array.isArray(params?.input) ? _tuple(schemas.$ZodTuple, params?.input as any) : (params?.input ?? null),
output: params?.output ?? null,
});
}
export { _function as function };