You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用嵌套泛型参数定义TypeScript类型别名?

解决TypeScript中从嵌套泛型类型提取参数的问题

你遇到的问题本质是需要从已有的Handler<I, R>类型中自动提取出I和R,而不需要手动重复传入这两个类型参数。TypeScript的条件类型+infer关键字正好可以解决这个问题,让你实现只传入Handler类型就能生成对应的异步处理函数类型。

直接解决方案

你只需要用infer在条件类型中推断Handler的泛型参数,修改AsyncHandler的定义如下:

type NodeCallback<T> = (err?: Error | void, result?: T) => void
type Handler<I, R> = (event: I, callback: NodeCallback<R>) => void
type StrToNumHandler = Handler<string, number>

// 正确的AsyncHandler定义
type AsyncHandler<T extends Handler<any, any>> = 
  T extends Handler<infer I, infer R> 
    ? (event: I) => Promise<R> 
    : never;

// 现在可以直接传入StrToNumHandler,无需额外传I和R
type AsyncStrToNumHandler = AsyncHandler<StrToNumHandler>;
// 等价于:(event: string) => Promise<number>

原理说明

  • T extends Handler<any, any>:先约束T必须是Handler的某个具体实例类型;
  • T extends Handler<infer I, infer R>:使用infer关键字告诉TypeScript,当T匹配Handler<I, R>的结构时,自动推断出I(输入事件类型)和R(回调结果类型);
  • 最后返回(event: I) => Promise<R>,也就是把原来的回调式Handler转换成Promise风格的异步函数类型。

可选:提取通用工具类型

如果需要复用Handler的输入/输出类型提取逻辑,可以单独定义工具类型:

// 提取Handler的输入事件类型
type HandlerInput<T extends Handler<any, any>> = T extends Handler<infer I, any> ? I : never;
// 提取Handler的回调结果类型
type HandlerOutput<T extends Handler<any, any>> = T extends Handler<any, infer R> ? R : never;

// 基于工具类型定义AsyncHandler
type AsyncHandler<T extends Handler<any, any>> = (event: HandlerInput<T>) => Promise<HandlerOutput<T>>;

这种写法更清晰,后续如果需要单独获取某个Handler的输入或输出类型,直接用HandlerInput<StrToNumHandler>或HandlerOutput<StrToNumHandler>即可。

验证效果

现在你可以像期望的那样使用AsyncHandler,TypeScript会自动推导出正确的类型:

const asyncHandler: AsyncStrToNumHandler = (event) => {
  return Promise.resolve(event.length); // event被推断为string,返回值是Promise<number>
};

这样就彻底解决了重复传入类型参数的问题,代码更简洁且类型安全。

内容的提问来源于stack exchange,提问作者bilalq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:35:00