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

TypeScript泛型参数键的类型提示问题求助

解决TypeScript监听器工具的类型提示与推断问题

问题背景

我正在构建一个工具,接口初始定义如下:

interface F<M extends Record<string, Function>> {
  (
    listeners: M, 
    options: { filter: e => boolean }
  ): void
}

核心需求是让filter的参数e类型自动依赖传入的监听器:

  • 仅传入e1: (e: E1) => {}时,filter的e应为E1
  • 传入e1: (e: E1) => {}和e2: (e: E2) => {}时,filter的e应为E1 | E2

现有实现满足类型推断和键验证,但无法为listeners提供正确的键提示(输入时显示大量无关内容,而非仅T中定义的键):

type Arg<F> = F extends (e: infer A) => any ? A : never;

interface F<T> {
  <E extends keyof T>(
    listeners: Pick<T, E>, 
    options: { filter: (e: Arg<T[E]>) => boolean }
  ): void
}

解决方案

调整泛型约束方式,用Partial<T>的子集约束listeners,同时保留类型推断能力:

首先定义提取函数参数的工具类型:

type EventArg<Fn> = Fn extends (e: infer E) => unknown ? E : never;

重新定义工具接口:

interface F<T extends Record<string, (...args: any) => unknown>> {
  <Listeners extends Partial<T>>(
    listeners: Listeners,
    options: {
      filter: (e: EventArg<Listeners[keyof Listeners]>) => boolean;
    }
  ): void;
}

效果验证

  1. 类型提示正常:声明let f: F<{ e1: (e: E1) => void, e2: (e: E2) => void }>后,输入f({ })触发补全,会显示e1和e2作为可选键。
  2. filter参数推断正确:
    • 仅传入e1时,filter的e自动推断为E1
    • 传入e1和e2时,filter的e自动推断为E1 | E2
  3. 键验证有效:传入T中未定义的键(如e3)时,TypeScript会抛出类型错误。

原理说明

  • 用Listeners extends Partial<T>约束listeners,明确告知TypeScript:listeners的键只能是T的键,因此补全时会精准提示T中定义的键。
  • Listeners[keyof Listeners]获取所有传入的监听器函数类型,再通过EventArg提取参数类型,最终得到所有传入事件参数的联合类型,满足filter的类型推断需求。

内容的提问来源于stack exchange,提问作者jeron-diovis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:43:14