英文:
Typescript - Generic constraint to pass zod schema result into function as argument
问题
以下是您要翻译的内容:
"I am trying to build a custom controller function to reduce the bloat of my application. Wrapping try-catch, parsing a zod schema, and then merging the request zod schema into a single object exists in all of the handler functions, hence I wanted to have a wrapper to handle these for each request. But I want to ensure type safety while doing so. Here is the function I have so far:
function controller<
T extends B & Q & P,
B extends Record<string, any>,
Q extends Record<string, any>,
P extends Record<string, any>
>(handlerFn: (args: T) => Promise<any>, zodSchema: { parse: (data: unknown) => { body: B; query: Q; params: P } }) {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const r = zodSchema.parse(req);
const args = { ...r.body, ...r.params, ...r.query };
await handlerFn(args);
} catch (e) {
next(e);
}
};
}
It takes a handlerFn
, which is the core function, which takes a parameter T. It takes a zodSchema
as its second parameter, in which after parsing should validate and return body, query, and params fields since we are going to validate the Request object. I want the input of the handlerFn
to be merged body, query, and params.
Here is the error I am getting:
Argument of type 'B & P & Q' is not assignable to parameter of type 'T'.
'B & P & Q' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Record<string, any>'.
Any help is appreciated."
英文:
I am trying to build a custom controller function to reduce the bloat of my application. Wrapping try-catch, parsing a zod schema, and then merging the request zod schema into single object exists in all of the handler functions, hence I wanted to have a wrapper to handle these for each request. But I want to ensure type safety while doing so. Here is the function I have so far:
function controller<
T extends B & Q & P,
B extends Record<string, any>,
Q extends Record<string, any>,
P extends Record<string, any>
>(handlerFn: (args: T) => Promise<any>, zodSchema: { parse: (data: unknown) => { body: B; query: Q; params: P } }) {
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
try {
const r = zodSchema.parse(req);
const args = { ...r.body, ...r.params, ...r.query };
await handlerFn(args);
} catch (e) {
next(e);
}
};
}
It takes a handlerFn
, which is the core function, which takes a parameter T. It takes a zodSchema
as its second parameter, in which after parsing should validate and return body, query, and params fields since we are going to validate the Request object. I want the input of the handlerFn
to be merged body, query, and params.
Here is the error I am getting:
Argument of type 'B & P & Q' is not assignable to parameter of type 'T'.
'B & P & Q' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Record<string, any>'.
Any help is appreciated.
答案1
得分: 1
The problem is that T extends B & Q & P
is not the same as T = B & Q & P
, and T
may have some other fields; thus, B & Q & P
won't be considered as T
. Instead of using T
just use B & Q & P
directly on the handlerFn
:
function controller<
B extends Record<string, any>,
Q extends Record<string, any>,
P extends Record<string, any>
>(
handlerFn: (args: B & Q & P) => Promise<any>,
zodSchema: { parse: (data: unknown) => { body: B; query: Q; params: P } }
) {
return async (req: any, res: any, next: any) => {
try {
const r = zodSchema.parse(req);
const args = { ...r.body, ...r.params, ...r.query };
await handlerFn(args);
} catch (e) {
next(e);
}
};
}
英文:
The problem is that T extends B & Q & P
is not the same as T = B & Q & P
, and T
may have some other fields; thus, B & Q & P
won't be considered as T
. Instead of using T
just use B & Q & P
directly on the handlerFn
:
function controller<
B extends Record<string, any>,
Q extends Record<string, any>,
P extends Record<string, any>
>(
handlerFn: (args: B & Q & P) => Promise<any>,
zodSchema: { parse: (data: unknown) => { body: B; query: Q; params: P } }
) {
return async (req: any, res: any, next: any) => {
try {
const r = zodSchema.parse(req);
const args = { ...r.body, ...r.params, ...r.query };
await handlerFn(args);
} catch (e) {
next(e);
}
};
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论