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

TypeScript条件类型问题:区分RPC服务的Call/Notify方法

解决TypeScript条件类型区分RPC Call/Notify方法的问题

问题原因

你遇到的问题本质是TypeScript中函数返回值的可替代性规则:返回void的函数类型是所有函数的超类型。也就是说,任何函数(哪怕它实际返回number、string等具体值)都可以赋值给返回void的函数类型。这就导致你原来的条件判断T[K] extends (...args: any[]) => void会匹配所有方法,不管它实际返回什么。

解决方案

要严格区分返回void和非void的方法,需要用严格类型相等检查替代子类型判断。可以通过将返回值包裹在元组中([R] extends [void])来实现,因为元组的类型比较是严格的,不会触发子类型兼容规则。

修改后的条件类型定义如下:

type CallMethods<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => infer R 
    ? [R] extends [void] ? never : K 
    : never;
}[keyof T];

type NotifyMethods<T> = {
  [K in keyof T]: T[K] extends (...args: any[]) => infer R 
    ? [R] extends [void] ? K : never 
    : never;
}[keyof T];

验证结果

对于你的ExampleService接口:

export default interface ExampleService {
  add(a: number, b: number): number;
  sub(a: number, b: number): number;
  log(message: string): void;
}
  • CallMethods<ExampleService> 会正确推导为 "add" | "sub"
  • NotifyMethods<ExampleService> 会正确推导为 "log"

原理说明

用[R] extends [void]替代直接的R extends void,是因为TypeScript对元组类型的比较是严格类型相等,而不是子类型兼容。这样就能精准识别出那些返回类型确实是void的方法,避免把返回具体值的方法误判为void返回。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:37:20