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

TypeScript如何限制继承BaseWidget的子类State的phases键的类型?

解决方案

可以实现你要的类型细化效果,确实需要通过泛型实现,你提到的将索引签名替换为映射类型的思路是正确的,具体实现如下:

第一步:改造基类与State类型为泛型结构

// 泛型参数T约束为字符串类型,代表phases允许的键名,默认值为string兼容原有无限制的使用场景
type State<T extends string = string> = {
  playing: boolean
  phases: {
    [key in T]: {
      progress: number
    }
  }
}

// BaseWidget同步声明泛型参数,透传给State
class BaseWidget<T extends string = string> {
  state: State<T>

  constructor() {
    this.state = {
      playing: false,
      // 这里做类型断言是因为初始化时phases为空,后续子类会完成赋值,属于合理的类型收窄
      phases: {} as State<T>['phases'],
    }
  }
}

第二步:子类继承时传入具体的键名联合类型

// 尖括号中传入允许的phases键的联合类型,即可完成类型细化
class Widget extends BaseWidget<'start' | 'finish'> {
    constructor() {
        super()
        this.state.phases = {
            start: {
                progress: 0,
            },
            finish: {
                progress: 0,
            },
        }
        // 此时如果新增其他键(如middle)、或者缺失start/finish任意一个,TS都会抛出类型错误
    }
}

核心说明

  • 泛型参数T的默认值设为string,不需要限制phases键的旧子类不需要做任何改动,完全兼容原有逻辑
  • 映射类型[key in T]会严格匹配传入的联合类型成员,实现对phases键的精确限制
  • 如果需要进一步复用阶段键的类型,也可以单独抽离类型定义:
    type WidgetPhases = 'start' | 'finish'
    class Widget extends BaseWidget<WidgetPhases> {}
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:54:03