Skip to content

Commit b659113

Browse files
committed
feat: enhance zodToTypeString to handle recursive schemas and improve error reporting
1 parent 0bf8825 commit b659113

1 file changed

Lines changed: 22 additions & 3 deletions

File tree

ts/src/internal/zod-schema.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,34 @@ function buildOverrides(skip: ZodTypeAny): TypeOverrideMap {
3030
}
3131

3232
export function zodToTypeString(schema: ZodTypeAny): string {
33+
const selfIdentifier = schemaRegistry.get(schema);
34+
const auxiliaryTypeStore = createAuxiliaryTypeStore();
35+
let rootVisited = false;
3336
const {node} = zodToTs(schema, {
34-
auxiliaryTypeStore: createAuxiliaryTypeStore(),
37+
auxiliaryTypeStore,
3538
overrides: buildOverrides(schema),
39+
overrideFunction: (candidate, typescript) => {
40+
if (candidate !== schema || selfIdentifier === undefined) return undefined;
41+
if (!rootVisited) {
42+
rootVisited = true;
43+
return undefined;
44+
}
45+
return typescript.factory.createTypeReferenceNode(typescript.factory.createIdentifier(selfIdentifier));
46+
},
3647
});
37-
return printNode(node, {removeComments: true, omitTrailingSemicolon: true}).replace(/\s+/g, " ").trim();
48+
const type = printNode(node, {removeComments: true, omitTrailingSemicolon: true}).replace(/\s+/g, " ").trim();
49+
if (auxiliaryTypeStore.definitions.size > 0) {
50+
const subject = selfIdentifier ? `data type "${selfIdentifier}"` : "the schema";
51+
throw new Error(
52+
`Cannot generate a type string for ${subject}: it contains recursive schemas that cannot be inlined. ` +
53+
`Register each recursive schema as its own data type so it can be referenced by identifier.`
54+
);
55+
}
56+
return type;
3857
}
3958

4059
export function zodToRules(schema: ZodTypeAny): DefinitionDataTypeRule[] {
41-
const json = toJSONSchema(schema) as JsonSchema;
60+
const json = toJSONSchema(schema, {cycles: "ref"}) as JsonSchema;
4261
const rules: DefinitionDataTypeRule[] = [];
4362
if (json.pattern) {
4463
rules.push({config: {oneofKind: "regex", regex: {pattern: json.pattern}}});

0 commit comments

Comments
 (0)