泛型T继承U但Readonly<T>不满足约束的TypeScript问题
TypeScript中同时满足类继承与Readonly特性的解决方案
我认为这并非其他类似问题的重复,以下是最小复现示例:
class Indexer { private readonly someIndex = 200; public getIndex() { return this.someIndex; } } class Person extends Indexer {} class Something<T extends Indexer> { s = new Map<number, T>(); insert(t: T){ /* ... */ } } const c1 = new Something< Person >(); const c2 = new Something<Readonly<Person>>();
我的需求是:
- 类既要继承
Indexer - 又要具备
Readonly特性
但无法同时满足这两个条件,编译时出现如下错误:
$ npx tsc --target es2020 main.ts main.ts:13:26 - error TS2344: Type 'Readonly<Person>' does not satisfy the constraint 'Indexer'. Property 'someIndex' is missing in type 'Readonly<Person>' but required in type 'Indexer'. 13 const c2 = new Something<Readonly<Person>>(); ~~~~~~~~~~~~~~~~ main.ts:2:20 2 private readonly someIndex = 200; ~~~~~~~~~ 'someIndex' is declared here.
解决方案1:修改泛型约束为兼容只读类型
问题根源是Readonly<Person>会隐藏基类的私有属性,导致无法匹配Indexer的约束。把Something的泛型约束改成T extends Readonly<Indexer>,这样既支持原始类实例,也支持只读包装的实例:
class Something<T extends Readonly<Indexer>> { s = new Map<number, T>(); insert(t: T){ /* ... */ } } const c1 = new Something<Person>(); // 正常编译 const c2 = new Something<Readonly<Person>>(); // 正常编译
解决方案2:定义只读基类接口
如果不想修改原有泛型约束,可以创建一个包含Indexer公共属性的只读接口,扩展泛型的约束范围:
// 提取Indexer的公共属性并标记为只读 interface ReadonlyIndexer extends Readonly<Pick<Indexer, keyof Indexer>> {} class Something<T extends Indexer | ReadonlyIndexer> { s = new Map<number, T>(); insert(t: T){ /* ... */ } } const c2 = new Something<Readonly<Person>>(); // 正常编译
解决方案3:类型断言临时绕过(不推荐)
如果只是临时场景需要,可以用类型断言跳过检查,但这会丢失TypeScript的类型安全性,不建议在正式代码中使用:
const c2 = new Something<Person>() as Something<Readonly<Person>>;
内容的提问来源于stack exchange,提问作者OrenIshShalom
相关产品推荐
相关产品推荐

