自定义Middy中间件结合Zod解析请求体的TypeScript类型错误排查
解决Middy中间件Zod类型不匹配错误
问题场景
自定义Middy中间件用Zod解析event.body并将类型化结果存入请求,但调用中间件时触发TypeScript类型错误:
TS2344: Type '{ email: string; password: string; }' does not satisfy the constraint 'ZodType<any, ZodTypeDef, any>'. Type '{ email: string; password: string; }' is missing the following properties from type 'ZodType<any, ZodTypeDef, any>': _type, _output, _input, _def, and 29 more.
错误原因
调用parseBody时手动传入了schemaType作为泛型参数,而schemaType是Zod解析后的普通对象类型,但parseBody的泛型约束要求传入的是ZodType(即Zod schema本身的类型),两者类型不匹配导致报错。
修复方案
1. 移除手动指定的泛型参数
调用parseBody时不需要手动传泛型,TypeScript会自动根据传入的schema推导正确的Zod类型,避免类型混淆。
2. 优化中间件泛型定义(可选,提升可读性)
调整TypedAPIGatewayProxyEvent和parseBody的泛型参数,让逻辑更直观:泛型直接对应解析后的类型,而非Zod schema类型。
修正后的完整代码
中间件部分
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda'; import middy from '@middy/core'; import z, { ZodType } from 'zod'; // 调整泛型:直接接受解析后的类型T export interface TypedAPIGatewayProxyEvent<T> extends APIGatewayProxyEvent { middy: { event: { typedBody: T; }; }; } export const parseBody = <T>( schema: ZodType<T> ): middy.MiddlewareObj<TypedAPIGatewayProxyEvent<T>, APIGatewayProxyResult> => { const before: middy.MiddlewareFn<TypedAPIGatewayProxyEvent<T>, APIGatewayProxyResult> = async (request): Promise<void> => { // 确保body已被jsonBodyParser解析为对象 const typedBody = schema.parse(request.event.body); // 简化对象赋值逻辑 request.event.middy = { ...request.event.middy, event: { ...request.event.middy?.event, typedBody } }; }; return { before }; };
Handler部分
import { APIGatewayProxyResult } from 'aws-lambda'; import middy from '@middy/core'; import { jsonBodyParser } from '@middy/http-json-body-parser'; import z, { TypeOf } from 'zod'; import { TypedAPIGatewayProxyEvent, parseBody } from './your-middleware-file'; const schema = z.object({ email: z.string(), password: z.string(), }); export type SchemaType = TypeOf<typeof schema>; export const handler = async (input: TypedAPIGatewayProxyEvent<SchemaType>): Promise<APIGatewayProxyResult> => { const typedBody = input.middy.event.typedBody; return { statusCode: 200, body: JSON.stringify({ email: typedBody.email, password: typedBody.password }) }; }; // 调用parseBody时无需手动指定泛型,TS自动推导 export const handlerWithMiddleware = middy(handler) .use(jsonBodyParser()) .use(parseBody(schema));
关键说明
- 移除
parseBody<SchemaType>(schema)中的泛型参数后,TS会根据传入的schema自动识别其对应的Zod类型,并推导解析后的T类型。 - 调整
TypedAPIGatewayProxyEvent的泛型为解析后的类型,让handler的输入类型更直观,无需再关联Zod schema类型。
内容的提问来源于stack exchange,提问作者zlZimon
相关产品推荐
相关产品推荐

