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
相关产品推荐
相关产品推荐

