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; }
效果验证
- 类型提示正常:声明
let f: F<{ e1: (e: E1) => void, e2: (e: E2) => void }>后,输入f({ })触发补全,会显示e1和e2作为可选键。 - filter参数推断正确:
- 仅传入
e1时,filter的e自动推断为E1 - 传入
e1和e2时,filter的e自动推断为E1 | E2
- 仅传入
- 键验证有效:传入
T中未定义的键(如e3)时,TypeScript会抛出类型错误。
原理说明
- 用
Listeners extends Partial<T>约束listeners,明确告知TypeScript:listeners的键只能是T的键,因此补全时会精准提示T中定义的键。 Listeners[keyof Listeners]获取所有传入的监听器函数类型,再通过EventArg提取参数类型,最终得到所有传入事件参数的联合类型,满足filter的类型推断需求。
内容的提问来源于stack exchange,提问作者jeron-diovis
相关产品推荐
相关产品推荐

