Versions
"@zodios/core": "10.9.4",
"zod": "3.22.1"
Number of Endpoints: 73
Number of Schemas: 403
I tried the 11.0.0-beta.19 version, failed with the same.
Context
We are trying to switch from an open api -> axios setup (used swagger-typescript-api) into a open api -> zodios setup (used openapi-zod-client).
We also using the composite flag from typescript in the monorepo, to improve typescript performance.
Issue
I use the example as a base, to illustrate the possible rootcause, the actual contract file I can provide on request but it seems not related to the actual setup, it's more about the complexity / amount of the endpoints.
Actual TS error:
The inferred type of this node exceeds the maximum length the compiler will serialize. An explicit type annotation is needed.
The issue reported from the following approaches
new Zodios(baseUrl, endpoints, options)
and the
makeApi(endpoints)
If I start to reduce the number of endpoint and shared schemas it will start to pass.
Simple example:
Schemas + client
import { Zodios, type ZodiosOptions } from '@zodios/core'
import { z } from 'zod'
export const Category = z.object({ id: z.number().int(), name: z.string() }).partial()
export type Category = z.infer<typeof Category>
export const Tag = z.object({ id: z.number().int(), name: z.string() }).partial()
export type Tag = z.infer<typeof Tag>
export const Pet = z.object({
id: z.number().int().optional(),
name: z.string(),
category: Category.optional(),
photoUrls: z.array(z.string()),
tags: z.array(Tag).optional(),
status: z.enum(['available', 'pending', 'sold']).optional(),
})
export type Pet = z.infer<typeof Pet>
export const createApiClient = (baseUrl: string, options?: ZodiosOptions) =>
new Zodios(
baseUrl,
[
{
method: 'put',
path: '/pet',
alias: 'updatepet',
description: `Update an existing pet by Id`,
requestFormat: 'json',
parameters: [
{
name: 'body',
description: `Update an existent pet in the store`,
type: 'Body',
schema: Pet,
},
],
response: Pet,
errors: [
{
status: 400,
description: `Invalid ID supplied`,
schema: z.void(),
},
{
status: 404,
description: `Pet not found`,
schema: z.void(),
},
{
status: 405,
description: `Validation exception`,
schema: z.void(),
},
],
},
],
options,
)
Typescript d.ts file output
import { type ZodiosOptions } from '@zodios/core';
import { z } from 'zod';
export declare const Category: z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>;
export type Category = z.infer<typeof Category>;
export declare const Tag: z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>;
export type Tag = z.infer<typeof Tag>;
export declare const Pet: z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodString;
category: z.ZodOptional<z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>>;
photoUrls: z.ZodArray<z.ZodString, "many">;
tags: z.ZodOptional<z.ZodArray<z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>, "many">>;
status: z.ZodOptional<z.ZodEnum<["available", "pending", "sold"]>>;
}, "strip", z.ZodTypeAny, {
name: string;
photoUrls: string[];
id?: number | undefined;
category?: {
id?: number | undefined;
name?: string | undefined;
} | undefined;
tags?: {
id?: number | undefined;
name?: string | undefined;
}[] | undefined;
status?: "available" | "pending" | "sold" | undefined;
}, {
name: string;
photoUrls: string[];
id?: number | undefined;
category?: {
id?: number | undefined;
name?: string | undefined;
} | undefined;
tags?: {
id?: number | undefined;
name?: string | undefined;
}[] | undefined;
status?: "available" | "pending" | "sold" | undefined;
}>;
export type Pet = z.infer<typeof Pet>;
export declare const createApiClient: (baseUrl: string, options?: ZodiosOptions) => import("@zodios/core").ZodiosInstance<[{
method: "put";
path: "/pet";
alias: "updatepet";
description: "Update an existing pet by Id";
requestFormat: "json";
parameters: [{
name: "body";
description: string;
type: "Body";
schema: z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodString;
category: z.ZodOptional<z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>>;
photoUrls: z.ZodArray<z.ZodString, "many">;
tags: z.ZodOptional<z.ZodArray<z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>, "many">>;
status: z.ZodOptional<z.ZodEnum<["available", "pending", "sold"]>>;
}, "strip", z.ZodTypeAny, {
name: string;
photoUrls: string[];
id?: number | undefined;
category?: {
id?: number | undefined;
name?: string | undefined;
} | undefined;
tags?: {
id?: number | undefined;
name?: string | undefined;
}[] | undefined;
status?: "available" | "pending" | "sold" | undefined;
}, {
name: string;
photoUrls: string[];
id?: number | undefined;
category?: {
id?: number | undefined;
name?: string | undefined;
} | undefined;
tags?: {
id?: number | undefined;
name?: string | undefined;
}[] | undefined;
status?: "available" | "pending" | "sold" | undefined;
}>;
}];
response: z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodString;
category: z.ZodOptional<z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>>;
photoUrls: z.ZodArray<z.ZodString, "many">;
tags: z.ZodOptional<z.ZodArray<z.ZodObject<{
id: z.ZodOptional<z.ZodNumber>;
name: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
id?: number | undefined;
name?: string | undefined;
}, {
id?: number | undefined;
name?: string | undefined;
}>, "many">>;
status: z.ZodOptional<z.ZodEnum<["available", "pending", "sold"]>>;
}, "strip", z.ZodTypeAny, {
name: string;
photoUrls: string[];
id?: number | undefined;
category?: {
id?: number | undefined;
name?: string | undefined;
} | undefined;
tags?: {
id?: number | undefined;
name?: string | undefined;
}[] | undefined;
status?: "available" | "pending" | "sold" | undefined;
}, {
name: string;
photoUrls: string[];
id?: number | undefined;
category?: {
id?: number | undefined;
name?: string | undefined;
} | undefined;
tags?: {
id?: number | undefined;
name?: string | undefined;
}[] | undefined;
status?: "available" | "pending" | "sold" | undefined;
}>;
errors: [{
status: 400;
description: string;
schema: z.ZodVoid;
}, {
status: 404;
description: string;
schema: z.ZodVoid;
}, {
status: 405;
description: string;
schema: z.ZodVoid;
}];
}]>;
What I tried to illustrate above, that with a single endpoint and with very 3 simple schemas, typescript compilation produced 260% larger file, and it seems it tries to calculate the type of every schema at least twice. (schema declaration and the API response/body declaration. In comprehension the exported type, where I just rely on z.infer it preserves as a reference.
Actual fails stats:
With the very same structure as above:
Client + Schemas LOC: 5048
When I store every endpoint as a const and remove the makeApi/newZodios and TS success on compile, LOC: 432500
Do you have any suggestion? Do I missed something?
Versions
Number of Endpoints:
73Number of Schemas:
403I tried the 11.0.0-beta.19 version, failed with the same.
Context
We are trying to switch from an open api -> axios setup (used
swagger-typescript-api) into a open api -> zodios setup (usedopenapi-zod-client).We also using the
compositeflag from typescript in the monorepo, to improve typescript performance.Issue
I use the example as a base, to illustrate the possible rootcause, the actual contract file I can provide on request but it seems not related to the actual setup, it's more about the complexity / amount of the endpoints.
Actual TS error:
The issue reported from the following approaches
new Zodios(baseUrl, endpoints, options)and the
makeApi(endpoints)If I start to reduce the number of endpoint and shared schemas it will start to pass.
Simple example:
Schemas + client
Typescript d.ts file output
What I tried to illustrate above, that with a single endpoint and with very 3 simple schemas, typescript compilation produced 260% larger file, and it seems it tries to calculate the type of every schema at least twice. (schema declaration and the API response/body declaration. In comprehension the exported type, where I just rely on z.infer it preserves as a reference.
Actual fails stats:
With the very same structure as above:
Client + Schemas LOC:
5048When I store every endpoint as a const and remove the makeApi/newZodios and TS success on compile, LOC:
432500Do you have any suggestion? Do I missed something?