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

TypeScript泛型类:如何让getSmth方法根据泛型类型按需抽象

嘿,这个问题挺有意思的!你想要的效果是让泛型基类根据T是否为默认的{},自动切换getSmth方法的行为——要么提供默认实现,要么强制子类重写。你原来的代码之所以没生效,是因为不管T是什么类型,父类都给了getSmth的具体实现,TypeScript自然不会要求子类重写啦。

下面给你两种可行的实现方式:

方法一:通过类型别名选择不同基类

这种方式最直接,我们定义两个基类:一个给T={}的情况提供默认实现,另一个给其他T定义抽象方法,然后用条件类型让Base根据T自动选择继承哪个类:

// 当T是{}时的基类,包含getSmth的默认实现
abstract class BaseWithDefault {
  public getSmth(): {} {
    return {};
  }
}

// 当T不是{}时的抽象基类,强制子类实现getSmth
abstract class BaseWithAbstract<T> {
  public abstract getSmth(): T;
}

// 根据泛型T的类型,选择对应的基类
type Base<T = {}> = T extends {} ? {} extends T ? BaseWithDefault : BaseWithAbstract<T> : BaseWithAbstract<T>;

// 测试用例
class A extends Base<{}> {
  // 不需要重写getSmth,继承了BaseWithDefault的实现
}

class B extends Base<{ x: number }> {
  // 必须重写getSmth,否则TypeScript会报错
  public getSmth(): { x: number } {
    return { x: 42 };
  }
}

方法二:利用条件类型和类型不匹配强制重写

如果不想拆分多个基类,也可以在单个基类里通过条件类型让默认实现的返回类型在T≠{}时不匹配,从而强制子类重写:

abstract class Base<T = {}> {
  // 当T是{}时返回{},否则返回never(让默认实现类型不合法)
  public getSmth(): T extends {} ? {} extends T ? {} : never : never {
    // 运行时判断,仅当T是{}时返回默认值
    return {} as any;
  }
}

class A extends Base<{}> {
  // 正常使用,无需重写
}

class B extends Base<{ x: number }> {
  // 必须重写getSmth,否则调用时会出现类型错误(返回never无法赋值给{ x: number })
  public getSmth(): { x: number } {
    return { x: 123 };
  }
}

原理说明

第一种方法的核心是用条件类型动态选择基类:当T严格等于{}(即T extends {}且{} extends T)时,继承带默认实现的类;否则继承带抽象方法的类,TypeScript会自动强制子类实现抽象方法。

第二种方法则是利用类型不匹配:当T≠{}时,父类getSmth的返回类型是never,而子类需要返回T类型的值,所以必须重写方法来修正类型,否则会触发类型错误。

两种方法都能满足你的需求,第一种更直观,类型提示也更清晰,推荐使用~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:18:21