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

TypeScript中类方法依构造函数选项实现条件返回类型

问题:根据构造函数选项切换类方法的返回类型

我确信这在TypeScript中可以实现,但找到的相关方案对我无效。

我需要实现一个类,其构造函数接收选项参数,让getData方法的返回类型根据multiple选项在string和string[]间切换:

(new MyClass({ multiple: true })).getData(); // 期望返回string[]
(new MyClass({ multiple: false })).getData(); // 期望返回string

我尝试了两种方案,但都遇到相同的类型错误:

方案1:将整个选项对象设为泛型

type Options = {
  multiple: boolean;
}

class MyClass<O extends Options> {
  constructor(private options: O) {}

  public getData = (): O["multiple"] extends true ? string[] : string => {
    if (this.options.multiple) {
      return ["foo", "bar"] as string[];
    }

    return "foo" as string;
  };
}

报错信息:TS2322: Type 'string[]' is not assignable to type 'O["multiple"] extends true ? string[] : string'

方案2:仅将multiple字段设为泛型

class Day<TReturnsArray extends boolean> {
  constructor(private options: { multiple: TReturnsArray }) {}

  public getData = (): TReturnsArray extends true ? string[] : string => {
    if (this.options.multiple) {
      return ["foo", "bar"] as string[];
    }

    return "foo" as string;
  };
}

同样触发上述错误,我不清楚为什么string[]无法匹配这个条件返回类型,错误信息也没有进一步的说明。


解决方案

问题根源在于TypeScript无法在条件分支中自动推断泛型条件类型的具体分支。以下是几种可行的解决方式:

方法1:精准类型断言

在每个返回分支中,将值断言为对应分支的条件类型,明确告诉TypeScript当前返回值符合该分支的类型要求:

class MyClass<TReturnsArray extends boolean> {
  constructor(private options: { multiple: TReturnsArray }) {}

  public getData(): TReturnsArray extends true ? string[] : string {
    if (this.options.multiple) {
      return ["foo", "bar"] as TReturnsArray extends true ? string[] : never;
    } else {
      return "foo" as TReturnsArray extends true ? never : string;
    }
  }
}

方法2:使用函数重载

通过给构造函数和getData方法定义重载签名,让TypeScript直接根据传入的选项参数推断返回类型,这种方式不需要泛型,代码更直观:

class MyClass {
  private readonly multiple: boolean;

  // 构造函数重载
  constructor(options: { multiple: true });
  constructor(options: { multiple: false });
  constructor(options: { multiple: boolean }) {
    this.multiple = options.multiple;
  }

  // getData方法重载
  getData(): string[];
  getData(): string;
  getData(): string | string[] {
    if (this.multiple) {
      return ["foo", "bar"];
    }
    return "foo";
  }
}

// 测试验证
const multiInstance = new MyClass({ multiple: true });
const multiResult = multiInstance.getData(); // 类型自动推断为string[]

const singleInstance = new MyClass({ multiple: false });
const singleResult = singleInstance.getData(); // 类型自动推断为string

方法3:自定义类型守卫

通过自定义类型守卫函数,帮助TypeScript在条件分支中缩小实例的泛型类型范围:

class MyClass<TReturnsArray extends boolean> {
  constructor(private readonly options: { multiple: TReturnsArray }) {}

  // 自定义类型守卫,判断当前实例是否为multiple=true的情况
  private isMultiple(): this is MyClass<true> {
    return this.options.multiple;
  }

  public getData(): TReturnsArray extends true ? string[] : string {
    if (this.isMultiple()) {
      return ["foo", "bar"]; // TypeScript now knows this branch returns string[]
    } else {
      return "foo"; // TypeScript now knows this branch returns string
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:45:36