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

如何在TypeScript函数签名中应用可辨识联合实现返回类型自动推导

问题原因

你当前的泛型约束是直接作用于函数联合类型,TypeScript 无法通过入参的可辨识字段type反向推导出你传入的参数对应联合中的哪一个函数类型,所以会默认将泛型推导为整个联合类型,最终返回值自然也是所有函数返回值的联合。

解决方案

不需要修改你已有的函数签名定义,只需要调整getFromFacade(以及第一个示例中的innerMethod)的泛型逻辑,让泛型直接约束可辨识字段type的字面量类型,再通过Extract匹配对应的参数和返回值类型即可。

第一个示例的修改代码

type fun1 = (opts: {type: 'a', value: string}) => string;
type fun2 = (opts: {type: 'b', value: number}) => number;

type anyFun = fun1 | fun2;

class Clazz {
  // 仅修改 innerMethod 的泛型定义
  innerMethod<T extends Parameters<anyFun>[0]['type']>(
    opts: Extract<Parameters<anyFun>[0], { type: T }>
  ): Extract<anyFun, (opts: {type: T}) => any> extends (...args: any) => infer R ? R : never {
    // 你的业务逻辑保持不变
    return 123 as any;
  }

  otherMethod() {
    // 现在自动推导返回类型为 string,符合预期
    const result1 = this.innerMethod({type: 'a', value: 'str'});
    // 自动推导返回类型为 number
    const result2 = this.innerMethod({type: 'b', value: 123});
  }
}

实际业务场景的修改代码

你只需要修改AbstractService中的getFromFacade方法的签名即可,其他已有定义完全不需要改动:

type Fork = number;
type Spoon = string;

type GetFork = (arg: {type: 'fork', id: number}) => Fork;
type GetSpoon = (arg: {type: 'spoon', id: number}) => Spoon;

interface Facade {
  constructor(services: AbstractService[]);
  get(request): any;
}

class AbstractService<NeedGetters extends (arg: any) => any = never> {
  facade!: Facade;

  init(facade: Facade) {
    this.facade = facade;
  }

  // 仅修改这个方法的泛型定义
  getFromFacade<T extends Parameters<NeedGetters>[0]['type']>(
    opts: Extract<Parameters<NeedGetters>[0], { type: T }>
  ): Extract<NeedGetters, (arg: {type: T}) => any> extends (...args: any) => infer R ? R : never {
    return this.facade.get(opts);
  }
}

interface ForksService extends AbstractService {
  getFork({type}: Parameters<GetFork>[0]): ReturnType<GetFork>;
}

interface SpoonsService extends AbstractService {
  getSpoon({type}: Parameters<GetSpoon>[0]): ReturnType<GetSpoon>;
}

class StuffService extends AbstractService<GetFork | GetSpoon> {
  someMethod() {
    // 现在自动推导类型为 number,符合预期
    const fork = this.getFromFacade({type: 'fork', id: 25});
    // 现在自动推导类型为 string,符合预期
    const spoon = this.getFromFacade({type: 'spoon', id: 36});
  }
}

扩展说明

如果你后续新增更多的 getter 函数,只需要照常把函数类型加到AbstractService的泛型联合里即可,不需要修改其他逻辑,可辨识字段的推导会自动生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 04:24:09