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

TypeScript:如何根据函数值的回调参数特征筛选对象键名

解决TypeScript筛选符合回调要求的事件键名问题

我来帮你搞定这个类型定义的问题!核心是要精准约束最后一个参数的类型,同时先确保我们处理的对象值都是函数类型,避免你遇到的约束错误。

完整解决方案代码

// 辅助类型:获取数组的最后一个元素
type Last<T extends any[]> = T extends [...infer _, infer L] ? L : never;

// 辅助类型:判断一个函数是否是「接受单个任意参数且返回void」的回调
type IsValidCallback<F> = 
  F extends (arg: any) => void ? true : false;

// 核心类型:筛选出符合要求的事件键名
type EventsWithCallback<T extends Record<string, (...args: any[]) => any>> = 
  keyof { 
    [P in keyof T as 
      IsValidCallback<Last<Parameters<T[P]>>> extends true 
        ? P 
        : never
    ]: T[P] 
  };

// 你的示例测试
interface Events {
  'valid0': (data: string, cb: () => void) => void, // 符合要求
  'valid1': (data: number, cb: (data: string) => void) => void, // 符合要求
  'invalid0': (data: string, cb: () => string) => void, // 不符合要求:回调返回类型错误
  'invalid1': (data: string, cb: (string: string, number: number) => void) => void, // 不符合要求:回调参数数量错误
}

type testFunction<E> = (eventName: EventsWithCallback<E>) => void;

// 测试:应该只允许传入'valid0' | 'valid1'
const test: testFunction<Events> = (eventName) => {
  console.log(eventName);
};

test('valid0'); // ✅ 正常
test('valid1'); // ✅ 正常
// test('invalid0'); // ❌ 类型错误
// test('invalid1'); // ❌ 类型错误

关键细节解释

  1. 约束输入类型T:
    我们给EventsWithCallback加上了T extends Record<string, (...args: any[]) => any>的约束,确保T的所有键对应的值都是函数,这样Parameters<T[P]>就不会出现你之前遇到的Type 'T[P]' does not satisfy the constraint '(...args: any[]) => void'错误。

  2. 精准判断回调类型:
    IsValidCallback类型专门用来校验回调:

    • 要求回调是一个函数
    • 接受恰好一个任意类型的参数(对应你示例里的valid1情况)
    • 返回值必须是void(排除invalid0这种返回string的情况)
  3. 过滤符合要求的键:
    利用TypeScript的映射类型as子句,遍历T的每个键P:

    • 先取该键对应函数的参数列表Parameters<T[P]>
    • 获取最后一个参数Last<...>
    • 用IsValidCallback判断是否符合要求,符合则保留键P,否则设为never(会被自动过滤)

为什么你之前的代码有问题?

  • 没有给T加上函数对象的约束,导致Parameters<T[P]>可能接收到非函数类型,触发错误
  • extends Function过于宽泛,会匹配所有函数类型,无法精准限制参数数量和返回值类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:03:10