I created and endpoint that uses a function which can return 3 different types based on one argument.
The function is getFile and the argument is serveAs: 'stream' | 'url' | 'data'. The way I coded it is function overload statements.
Because we are using sequelize v6, the model is still "in js code" and lacks proper and robust typing. The model is simply the File returned from the topmost overload, and at that point is a JSON object (calling toJSON after getting the response from the db).
The contract for this endpoint is declared as a z.union
z.union([
// For serveAs: url
z.object({ url: z.string() }),
// For serveAs: file
z.instanceof(Stream),
// For serveAs: data
FileDto
])
where FileDto is the schema reflecting the db model z.object({ ... }).
Localy it runs fine. No problems whatsoever. But once I pushed the code for a PR our github action for testing failed complaining.
Error: Jest: Got error running globalSetup - /codebuild ... testSetup.js, reason: [TSError: app/controllers/emi/files.controller.ts:32:14 - error TS2322: Type '({ params, res, query }: { params: { id: string; }; query: { serveAs?: "data" | "file" | "presigned-url" | undefined; expiresIn?: number | undefined; }; headers: { [x: string]: string | string[] | undefined; [x: number]: string | ... 1 more ... | undefined; authorization?: string | undefined; "x-product-name"?: stri...' is not assignable to type 'AppRouteQueryImplementation<{ metadata: { 'x-audience': Audience; tags: string[]; operationId: string; }; method: "GET"; description: "Get file by id"; query: ZodObject<{ serveAs: ZodOptional<ZodEnum<["file", "presigned-url", "data"]>>; expiresIn: ZodOptional<...>; }, "strip", ZodTypeAny, { ...; }, { ...; }>; ... 4 ...'.
Type 'Promise<{ status: 200; body: Stream; } | { status: 200; body: string; } | { status: 200; body: File; }>' is not assignable to type 'Promise<Prettify<AppRouteResponses<{ metadata: { 'x-audience': Audience; tags: string[]; operationId: string; }; method: "GET"; description: "Get file by id"; query: ZodObject<{ serveAs: ZodOptional<ZodEnum<["file", "presigned-url", "data"]>>; expiresIn: ZodOptional<...>; }, "strip", ZodTypeAny, { ...; }, { ...; }>;...'.
Type '{ status: 200; body: Stream; } | { status: 200; body: { url: string }; } | { status: 200; body: File; }' is not assignable to type 'Prettify<AppRouteResponses<{ metadata: { 'x-audience': Audience; tags: string[]; operationId: string; }; method: "GET"; description: "Get file by id"; query: ZodObject<{ serveAs: ZodOptional<ZodEnum<["file", "presigned-url", "data"]>>; expiresIn: ZodOptional<...>; }, "strip", ZodTypeAny, { ...; }, { ...; }>; ... 4 m...'.
Type '{ status: 200; body: File; }' is not assignable to type 'Prettify<AppRouteResponses<{ metadata: { 'x-audience': Audience; tags: string[]; operationId: string; }; method: "GET"; description: "Get file by id"; query: ZodObject<{ serveAs: ZodOptional<ZodEnum<["file", "presigned-url", "data"]>>; expiresIn: ZodOptional<...>; }, "strip", ZodTypeAny, { ...; }, { ...; }>; ... 4 m...'.
Type '{ status: 200; body: File; }' is not assignable to type '{ status: 200; body: string | Stream | { key: string; location: string; id: string; metadata: { key: string; value: string; }[]; path: string; size: number; createdAt: Date; updatedAt: Date; ... 5 more ...; cdnLing?: string | undefined; }; }'.
Types of property 'body' are incompatible.
Type 'File' is not assignable to type '{ url: string } | Stream | { key: string; location: string; id: string; metadata: { key: string; value: string; }[]; path: string; size: number; createdAt: Date; updatedAt: Date; bucket: string; ... 4 more ...; cdnLing?: string | undefined; }'.
Type 'File' is missing the following properties from type '{ key: string; location: string; id: string; metadata: { key: string; value: string; }[]; path: string; size: number; createdAt: Date; updatedAt: Date; bucket: string; mimeType: string; originalName: string; extension: string; version?: string | undefined; cdnLing?: string | undefined; }': metadata, extension
32 export const findFileById: AppRouteImplementation<
~~~~~~~~~~~~]
at runGlobalHook
If I were to give up, I would just split the endpoint into three separate endpoints for each type. Just not sure if the problem wont be the same in the one that returns FileDto/File
Can anyone tell me what am I doing wrong here?
PS:
I can't fix the typo cdnLing - it does not appear in code anymore but pops up in the log on github...
We are using zod with ts-rest and node express.
I created and endpoint that uses a function which can return 3 different types based on one argument. The function is
getFile
and the argument isserveAs: 'stream' | 'url' | 'data'
. The way I coded it is function overload statements.Because we are using sequelize v6, the model is still "in js code" and lacks proper and robust typing. The model is simply the
File
returned from the topmost overload, and at that point is a JSON object (callingtoJSON
after getting the response from the db).The contract for this endpoint is declared as a
z.union
where FileDto is the schema reflecting the db model
z.object({ ... })
.Localy it runs fine. No problems whatsoever. But once I pushed the code for a PR our github action for testing failed complaining.
If I were to give up, I would just split the endpoint into three separate endpoints for each type. Just not sure if the problem wont be the same in the one that returns
FileDto/File
Can anyone tell me what am I doing wrong here?
PS: I can't fix the typo
cdnLing
- it does not appear in code anymore but pops up in the log on github...