Skip to content

Commit 9e95ba8

Browse files
committed
General fallback depending on direction, plus proper types for never, void and unknown.
1 parent 15e8dfa commit 9e95ba8

3 files changed

Lines changed: 56 additions & 26 deletions

File tree

express-zod-api/src/zts.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ const producers: HandlingRules<
212212
undefined: onPrimitive(ts.SyntaxKind.UndefinedKeyword),
213213
[ezDateInBrand]: onPrimitive(ts.SyntaxKind.StringKeyword),
214214
[ezDateOutBrand]: onPrimitive(ts.SyntaxKind.StringKeyword),
215+
never: onPrimitive(ts.SyntaxKind.NeverKeyword),
216+
void: onPrimitive(ts.SyntaxKind.UndefinedKeyword),
217+
unknown: onPrimitive(ts.SyntaxKind.UnknownKeyword),
215218
null: onNull,
216219
array: onArray,
217220
tuple: onTuple,
@@ -244,6 +247,6 @@ export const zodToTs = (
244247
) =>
245248
walkSchema(schema, {
246249
rules: { ...brandHandling, ...producers },
247-
onMissing: () => ensureTypeNode(ts.SyntaxKind.AnyKeyword), // @todo UnknownKeyword
250+
onMissing: ({}, { isResponse }) => getFallback(isResponse),
248251
ctx,
249252
});

express-zod-api/tests/__snapshots__/zts.spec.ts.snap

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ exports[`zod-to-ts > Example > should produce the expected results 1`] = `
1818
date: any;
1919
undefined: undefined;
2020
null: null;
21-
void: any;
21+
void: undefined;
2222
any: any;
23-
unknown: any;
24-
never: any;
23+
unknown: unknown;
24+
never: never;
2525
optionalString?: string | undefined;
2626
nullablePartialObject: {
2727
string?: string | undefined;
@@ -139,18 +139,33 @@ exports[`zod-to-ts > Issue #2352: intersection of objects having same prop %# >
139139
}"
140140
`;
141141

142-
exports[`zod-to-ts > PrimitiveSchema > outputs correct typescript 1`] = `
142+
exports[`zod-to-ts > PrimitiveSchema (isResponse=false) > outputs correct typescript 1`] = `
143143
"{
144144
string: string;
145145
number: number;
146146
boolean: boolean;
147147
date: any;
148148
undefined: undefined;
149149
null: null;
150-
void: any;
150+
void: undefined;
151151
any: any;
152-
unknown: any;
153-
never: any;
152+
unknown: unknown;
153+
never: never;
154+
}"
155+
`;
156+
157+
exports[`zod-to-ts > PrimitiveSchema (isResponse=true) > outputs correct typescript 1`] = `
158+
"{
159+
string: string;
160+
number: number;
161+
boolean: boolean;
162+
date: unknown;
163+
undefined: undefined;
164+
null: null;
165+
void: undefined;
166+
any: any;
167+
unknown: unknown;
168+
never: never;
154169
}"
155170
`;
156171

@@ -273,6 +288,8 @@ exports[`zod-to-ts > z.optional() > Zod 4: should add question mark only to opti
273288

274289
exports[`zod-to-ts > z.pipe() > transformations > should handle an error within the transformation 1`] = `"unknown"`;
275290

291+
exports[`zod-to-ts > z.pipe() > transformations > should handle preprocess error in request 1`] = `"any"`;
292+
276293
exports[`zod-to-ts > z.pipe() > transformations > should handle unsupported transformation in response 1`] = `"unknown"`;
277294

278295
exports[`zod-to-ts > z.pipe() > transformations > should produce the schema type 'intact' 1`] = `"number"`;

express-zod-api/tests/zts.spec.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -328,25 +328,28 @@ describe("zod-to-ts", () => {
328328
);
329329
});
330330

331-
describe("PrimitiveSchema", () => {
332-
const primitiveSchema = z.object({
333-
string: z.string(),
334-
number: z.number(),
335-
boolean: z.boolean(),
336-
date: z.date(),
337-
undefined: z.undefined(),
338-
null: z.null(),
339-
void: z.void(),
340-
any: z.any(),
341-
unknown: z.unknown(),
342-
never: z.never(),
343-
});
344-
const node = zodToTs(primitiveSchema, { ctx });
331+
describe.each([true, false])(
332+
"PrimitiveSchema (isResponse=%s)",
333+
(isResponse) => {
334+
const primitiveSchema = z.object({
335+
string: z.string(),
336+
number: z.number(),
337+
boolean: z.boolean(),
338+
date: z.date(),
339+
undefined: z.undefined(),
340+
null: z.null(),
341+
void: z.void(),
342+
any: z.any(),
343+
unknown: z.unknown(),
344+
never: z.never(),
345+
});
346+
const node = zodToTs(primitiveSchema, { ctx: { ...ctx, isResponse } });
345347

346-
test("outputs correct typescript", () => {
347-
expect(printNodeTest(node)).toMatchSnapshot();
348-
});
349-
});
348+
test("outputs correct typescript", () => {
349+
expect(printNodeTest(node)).toMatchSnapshot();
350+
});
351+
},
352+
);
350353

351354
describe("z.discriminatedUnion()", () => {
352355
const shapeSchema = z.discriminatedUnion("kind", [
@@ -392,6 +395,13 @@ describe("zod-to-ts", () => {
392395
).toMatchSnapshot();
393396
});
394397

398+
test("should handle preprocess error in request", () => {
399+
const schema = z.preprocess(() => {
400+
throw new Error("intentional");
401+
}, z.number());
402+
expect(printNodeTest(zodToTs(schema, { ctx }))).toMatchSnapshot();
403+
});
404+
395405
test("should handle an error within the transformation", () => {
396406
const schema = z
397407
.number()

0 commit comments

Comments
 (0)