Skip to content

Commit b588d2c

Browse files
committed
Improve z.function typing. Add .def
1 parent 7bd15ed commit b588d2c

File tree

4 files changed

+64
-47
lines changed

4 files changed

+64
-47
lines changed

packages/zod/src/v4/classic/tests/function.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ test("function inference 1", () => {
6868
test("args method", () => {
6969
const t1 = z.function();
7070
type t1 = (typeof t1)["_input"];
71-
expectTypeOf<t1>().toEqualTypeOf<(...args_1: unknown[]) => unknown>();
71+
expectTypeOf<t1>().toEqualTypeOf<(...args_1: never[]) => unknown>();
7272

7373
const t2args = z.tuple([z.string()], z.unknown());
7474

@@ -81,6 +81,14 @@ test("args method", () => {
8181
expectTypeOf<t3>().toEqualTypeOf<(arg: string, ...args_1: unknown[]) => boolean>();
8282
});
8383

84+
test("contravariance", () => {
85+
const fn = z.function().implement((_a: string, _b: number) => {
86+
return new Date();
87+
});
88+
89+
expectTypeOf(fn).toEqualTypeOf<(a: string, b: number) => Date>();
90+
});
91+
8492
const args2 = z.tuple([
8593
z.object({
8694
f1: z.number(),

packages/zod/src/v4/core/function.ts

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,47 @@ import type * as util from "./util.js";
1212
////////// //////////
1313
//////////////////////////////////////////
1414
//////////////////////////////////////////
15-
export interface $ZodFunctionDef /* extends schemas.$ZodTypeDef */ {
15+
export interface $ZodFunctionDef<
16+
In extends $ZodFunctionIn = $ZodFunctionIn,
17+
Out extends $ZodFunctionOut = $ZodFunctionOut,
18+
> {
1619
type: "function";
17-
input: $ZodFunctionArgs | null;
18-
output: schemas.$ZodType | null;
20+
input: In;
21+
output: Out;
1922
}
2023

2124
export type $ZodFunctionArgs = schemas.$ZodType<unknown[], unknown[]>;
25+
export type $ZodFunctionIn = $ZodFunctionArgs | null;
26+
export type $ZodFunctionOut = schemas.$ZodType | null;
2227

23-
export type $InferInnerFunctionType<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
24-
...args: Args["_zod"]["output"]
25-
) => Returns["_zod"]["input"];
28+
export type $InferInnerFunctionType<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
29+
...args: null extends Args ? never[] : NonNullable<Args>["_zod"]["output"]
30+
) => null extends Returns ? unknown : NonNullable<Returns>["_zod"]["input"];
2631

27-
export type $InferInnerFunctionTypeAsync<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
28-
...args: Args["_zod"]["output"]
29-
) => util.MaybeAsync<Returns["_zod"]["input"]>;
32+
export type $InferInnerFunctionTypeAsync<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
33+
...args: null extends Args ? never[] : NonNullable<Args>["_zod"]["output"]
34+
) => null extends Returns ? unknown : util.MaybeAsync<NonNullable<Returns>["_zod"]["input"]>;
3035

31-
export type $InferOuterFunctionType<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
32-
...args: Args["_zod"]["input"]
33-
) => Returns["_zod"]["output"];
36+
export type $InferOuterFunctionType<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
37+
...args: null extends Args ? never[] : NonNullable<Args>["_zod"]["input"]
38+
) => null extends Returns ? unknown : NonNullable<Returns>["_zod"]["output"];
3439

35-
export type $InferOuterFunctionTypeAsync<Args extends $ZodFunctionArgs, Returns extends schemas.$ZodType> = (
36-
...args: Args["_zod"]["input"]
37-
) => util.MaybeAsync<Returns["_zod"]["output"]>;
40+
export type $InferOuterFunctionTypeAsync<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
41+
...args: null extends Args ? never[] : NonNullable<Args>["_zod"]["input"]
42+
) => null extends Returns ? unknown : util.MaybeAsync<NonNullable<Returns>["_zod"]["output"]>;
3843

3944
export class $ZodFunction<
40-
Args extends $ZodFunctionArgs = $ZodFunctionArgs,
41-
Returns extends schemas.$ZodType = schemas.$ZodType,
45+
Args extends $ZodFunctionIn = $ZodFunctionIn,
46+
Returns extends $ZodFunctionOut = $ZodFunctionOut,
4247
> {
43-
_def: $ZodFunctionDef;
48+
_def: $ZodFunctionDef<Args, Returns>;
49+
def: $ZodFunctionDef<Args, Returns>;
4450
_input!: $InferInnerFunctionType<Args, Returns>;
4551
_output!: $InferOuterFunctionType<Args, Returns>;
4652

47-
constructor(def: $ZodFunctionDef) {
53+
constructor(def: $ZodFunctionDef<Args, Returns>) {
4854
this._def = def;
55+
this.def = def;
4956
}
5057

5158
implement<F extends $InferInnerFunctionType<Args, Returns>>(
@@ -59,7 +66,7 @@ export class $ZodFunction<
5966
if (!Array.isArray(parsedArgs)) {
6067
throw new Error("Invalid arguments schema: not an array or tuple schema.");
6168
}
62-
const output = func(...parsedArgs);
69+
const output = func(...(parsedArgs as any));
6370
return this._def.output ? parse(this._def.output, output, undefined, { callee: impl }) : output;
6471
}) as any;
6572
return impl;
@@ -77,17 +84,17 @@ export class $ZodFunction<
7784
if (!Array.isArray(parsedArgs)) {
7885
throw new Error("Invalid arguments schema: not an array or tuple schema.");
7986
}
80-
const output = await func(...parsedArgs);
87+
const output = await func(...(parsedArgs as any));
8188
return this._def.output ? parseAsync(this._def.output, output, undefined, { callee: impl }) : output;
8289
}) as any;
8390
return impl;
8491
}
8592

86-
input<const Items extends util.TupleItems, const Rest extends schemas.$ZodType | null = null>(
93+
input<const Items extends util.TupleItems, const Rest extends $ZodFunctionOut = null>(
8794
args: Items,
8895
rest?: Rest
8996
): $ZodFunction<schemas.$ZodTuple<Items, Rest>, Returns>;
90-
input<NewArgs extends $ZodFunctionArgs>(args: NewArgs): $ZodFunction<NewArgs, Returns>;
97+
input<NewArgs extends $ZodFunctionIn>(args: NewArgs): $ZodFunction<NewArgs, Returns>;
9198
input(...args: any[]): $ZodFunction<any, Returns> {
9299
if (Array.isArray(args[0])) {
93100
return new $ZodFunction({
@@ -116,19 +123,28 @@ export class $ZodFunction<
116123
}
117124
}
118125

119-
export interface $ZodFunctionParams<I extends $ZodFunctionArgs, O extends schemas.$ZodType> {
126+
export interface $ZodFunctionParams<I extends $ZodFunctionIn, O extends schemas.$ZodType> {
120127
input?: I;
121128
output?: O;
122129
}
123130

124131
function _function(): $ZodFunction;
132+
function _function<const In extends Array<schemas.$ZodType> = Array<schemas.$ZodType>>(params: {
133+
input: In;
134+
}): $ZodFunction<$ZodTuple<In, null>, null>;
135+
function _function<const In extends $ZodFunctionIn = $ZodFunctionIn>(params: {
136+
input: In;
137+
}): $ZodFunction<In, null>;
138+
function _function<const Out extends $ZodFunctionOut = $ZodFunctionOut>(params: {
139+
output: Out;
140+
}): $ZodFunction<null, Out>;
125141
function _function<
126-
const In extends Array<schemas.$ZodType> = Array<schemas.$ZodType>,
142+
In extends $ZodFunctionIn = $ZodFunctionIn,
127143
Out extends schemas.$ZodType = schemas.$ZodType,
128-
>(params?: { input?: In; output?: Out }): $ZodFunction<$ZodTuple<In, null>, Out>;
129-
function _function<In extends $ZodFunctionArgs = $ZodFunctionArgs, Out extends schemas.$ZodType = schemas.$ZodType>(
130-
params?: $ZodFunctionParams<In, Out>
131-
): $ZodFunction<In, Out>;
144+
>(params?: {
145+
input: In;
146+
output: Out;
147+
}): $ZodFunction<In, Out>;
132148
function _function(params?: {
133149
output?: schemas.$ZodType;
134150
input?: $ZodFunctionArgs | Array<schemas.$ZodType>;

play.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
import * as z from "zod/v4";
22

3-
z;
3+
export const a = z.object({
4+
asdf: z.iso.datetime(),
5+
});
46

5-
const result = z.toJSONSchema(z.date(), {
6-
unrepresentable: "any",
7-
override: (ctx) => {
8-
const def = ctx.zodSchema._zod.def;
9-
if (def.type === "date") {
10-
ctx.jsonSchema.type = "string";
11-
ctx.jsonSchema.format = "date-time";
12-
}
13-
},
7+
const fn = z.function({
8+
// input: z.tuple([z.string()], z.number()),
9+
output: z.string(),
1410
});
15-
/* => {
16-
type: 'string',
17-
format: 'date-time',
18-
'$schema': 'https://json-schema.org/draft/2020-12/schema'
19-
} */
20-
console.dir(result, { depth: null });
11+
12+
fn.def.output;
13+
fn.def.input;

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"extends": "./.configs/tsconfig.base.json",
33
"compilerOptions": {
44
"rootDir": ".",
5-
"noEmit": true
5+
"declaration": true
66
},
77
"exclude": ["packages/docs"]
88
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy