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

如何筛选对象中值为非Promise返回的函数类型的键?

TypeScript 类型过滤:筛选返回值非Promise的函数键

需求是编写一个TypeScript类型,过滤对象中值为函数且返回值不是Promise的键。现有代码中keys类型意外包含了返回Promise的"B",需要调整实现让它仅返回"A"。

现有代码问题分析

type FilterKeys<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];

type O = {
  A: () => void;
  B: () => Promise<void>;
};

// 当前结果:"A" | "B",不符合预期
type keys = FilterKeys<O, (e: never) => void>;

// 这个结果符合预期
type keys2 = FilterKeys<O, (e: never) => Promise<void>>;

问题出在TypeScript的函数类型协变特性:() => Promise<void>可以赋值给() => void(因为返回值Promise<void>兼容void类型,void允许忽略任何返回值),所以原有的extends判断会错误地把B也纳入匹配范围。

解决方案:精确判断返回值是否为Promise

我们需要修改类型逻辑,先确认值是函数类型,再排除返回值为Promise的情况:

// 直接构造目标类型,筛选返回值非Promise的函数键
type FilterNonPromiseReturnFunctionKeys<T> = {
  [K in keyof T]: 
    // 先判断当前键的值是否为函数类型
    T[K] extends (...args: any[]) => infer R 
      ? // 再判断函数返回值是否不是Promise
        R extends Promise<any> ? never : K 
      : never; // 非函数类型直接排除
}[keyof T];

type O = {
  A: () => void;
  B: () => Promise<void>;
  C: (id: string) => number; // 额外测试:返回普通值的函数
  D: boolean; // 额外测试:非函数类型
};

// 结果:"A" | "C",完全符合预期
type keys = FilterNonPromiseReturnFunctionKeys<O>;

如果想保留通用的FilterKeys结构,也可以先定义一个辅助类型来标记非Promise返回的函数:

// 辅助类型:仅保留返回值非Promise的函数类型,否则返回never
type NonPromiseReturnFunction<T> = 
  T extends (...args: any[]) => infer R 
    ? R extends Promise<any> ? never : T 
    : never;

// 复用原有的FilterKeys逻辑
type FilterKeys<T, U> = {
  [K in keyof T]: T[K] extends U ? K : never;
}[keyof T];

type O = {
  A: () => void;
  B: () => Promise<void>;
};

// 结果:"A",符合需求
type keys = FilterKeys<O, NonPromiseReturnFunction<(...args: any[]) => any>>;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:00:21