如何根据Handler参数类型自动推断compose返回的Middleware泛型参数?
TypeScript自动推断compose中间件返回类型的实现方案
你的核心需求是让compose返回的中间件函数,自动根据最终传入的handler返回值类型推断自身返回类型,无需显式指定泛型参数。这个需求完全可以实现,关键是把泛型推断的时机从调用compose时,延迟到调用返回的中间件函数时。
问题根源
原代码中compose<T>的泛型参数T在调用compose时就需要确定,但此时还未传入最终的handler,TypeScript只能将T推断为unknown,导致后续result.id报错。
解决方案
修改compose的定义,让它返回一个泛型中间件函数,而非提前绑定死T的中间件。具体代码如下:
export type Context = any; export type Handler<T> = (ctx: Context) => Promise<T>; export type Middleware<T> = (ctx: Context, handler: Handler<T>) => Promise<T>; // 移除compose自身的泛型参数,返回一个泛型的Middleware函数 export function compose(...middlewares: Middleware<unknown>[]): <T>Middleware<T> { return async function compositeMiddleware<T>( ctx: Context, handler: Handler<T> ): Promise<T> { // 中间件链式调用的示例实现 const chain = middlewares.reduceRight((next, middleware) => { return () => middleware(ctx, next); }, handler); return chain(ctx); }; }
修正中间件定义
为避免隐式类型问题,建议明确指定中间件的泛型为unknown(你的中间件仅透传结果,不依赖特定类型):
const middleware1: Middleware<unknown> = async (ctx, next) => { console.log('Middleware 1 Before'); const result = await next(ctx); console.log('Middleware 1 After'); return result; }; const middleware2: Middleware<unknown> = async (ctx: Context, next: Handler<unknown>) => { console.log('Middleware 2 Before'); const result = await next(ctx); console.log('Middleware 2 After'); return result; };
使用效果
现在调用compose得到的compositeMiddleware是一个泛型函数,传入最终handler时,TypeScript会自动推断返回类型:
const compositeMiddleware = compose(middleware1, middleware2); const result = await compositeMiddleware({}, async () => { return { id: 'mock-id' }; }); result.id; // 正确推断为string类型,无报错
原理说明
通过让compose返回<T>Middleware<T>,我们把泛型T的推断时机延迟到了调用compositeMiddleware的时候——此时TypeScript已能获取最终handler的返回值类型,自然可以自动推断出T,让result的类型完全匹配handler的返回类型。
内容的提问来源于stack exchange,提问作者brietsparks
相关产品推荐
相关产品推荐

