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

泛型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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:10:18