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

如何正确为TypeScript泛型类方法getFormattedOrOriginal标注类型?

TypeScript泛型类中根据构造函数参数自动推导方法返回类型

我定义了如下TypeScript泛型类Test,构造函数接收类型为A的value参数,以及可选的、将A转换为B的formatter函数(B默认值为A)。我希望getFormattedOrOriginal方法能自动根据构造函数是否传入formatter,返回对应类型:未传入时返回A类型,传入时返回B类型。目前仅能通过this.value as unknown as B的类型断言实现,但这显然不是好方案,请问该如何正确为该方法标注类型?

原代码:

class Test<A, B = A> {
  constructor(private value: A, private formatter?: (x: A) => B) {}

  getFormattedOrOriginal(): B {
    return this.formatter ? this.formatter(this.value) : this.value;
  }
}

// 预期行为:
new Test(3).getFormattedOrOriginal() === 3
new Test(3, x => x.toString()).getFormattedOrOriginal() === "3"

方案1:构造函数+方法重载(无安全风险)

通过重载明确不同参数组合下的类型关系,完全避免不安全的类型断言,逻辑清晰直观:

class Test<A> {
  private value: A;
  private formatter?: (x: A) => unknown;

  // 重载:未传入formatter的构造逻辑
  constructor(value: A);
  // 重载:传入formatter时,推导转换后的类型B
  constructor<B>(value: A, formatter: (x: A) => B);
  // 构造函数核心实现
  constructor(value: A, formatter?: (x: A) => unknown) {
    this.value = value;
    this.formatter = formatter;
  }

  // 重载:未传入formatter时返回原类型A
  getFormattedOrOriginal(): A;
  // 重载:传入formatter时返回转换后的类型B
  getFormattedOrOriginal<B>(): B;
  // 方法核心实现
  getFormattedOrOriginal() {
    return this.formatter ? this.formatter(this.value) : this.value;
  }
}

方案2:泛型条件类型(精确类型约束)

通过泛型参数结合条件类型,直接推导返回值类型。这里的类型断言是安全的,因为条件类型已经确保返回值与声明类型完全匹配:

class Test<A, F extends ((x: A) => unknown) | undefined = undefined> {
  constructor(private value: A, private formatter?: F) {}

  getFormattedOrOriginal(): F extends ((x: A) => infer B) ? B : A {
    return (this.formatter ? this.formatter(this.value) : this.value) as F extends ((x: A) => infer B) ? B : A;
  }
}

验证效果

两种方案都能满足预期类型推导:

// 未传入formatter,返回number类型
const numTest = new Test(3);
console.log(numTest.getFormattedOrOriginal() === 3); // true,类型为number

// 传入formatter,返回string类型
const strTest = new Test(3, x => x.toString());
console.log(strTest.getFormattedOrOriginal() === "3"); // true,类型为string

方案对比

  • 方案1更适合大多数场景,通过重载明确类型逻辑,无需任何断言,可读性强。
  • 方案2适合需要严格控制泛型参数的场景,通过条件类型精确约束类型关系,断言仅用于辅助TypeScript推导,无安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:16:06