TypeScript泛型抽象类中出现Property 'id'不存在于类型'User'错误
解决TypeScript泛型抽象类中访问领域模型属性报错的问题
问题场景复现
先还原你遇到问题的代码结构(基于描述模拟):
interface User { id: string; name: string; } class UserInstance implements User { id: string; name: string; constructor(id: string, name: string) { this.id = id; this.name = name; } } import { Model } from 'objection'; // 错误的泛型抽象类定义 abstract class AbstractModel<T> extends Model { abstract mapFromDB(): T; abstract mapToDB(domain: T): void; } class UserDetailModel extends AbstractModel<User> { mapFromDB(): User { return new UserInstance(this.id, this.name); } mapToDB(domain: User): void { // 报错:Property 'id' does not exist on type 'User'. ts(2339) this.id = domain.id; } } // 非泛型方法无异常 function test(user: User) { console.log(user.id); // 正常通过类型检查 }
错误原因
核心问题是泛型参数T没有添加类型约束:
- 在抽象类
AbstractModel<T>的定义中,T是无约束的任意类型,TypeScript无法确定所有传入的T都包含id属性。 - 哪怕你在
UserDetailModel中指定了泛型为User,但抽象类的mapToDB方法签名是基于无约束的T定义的,类型检查器会严格遵循抽象类的泛型约束进行校验,导致在实现方法时无法识别domain.id。 - 非泛型的
test方法没问题,是因为它直接明确了参数类型是User,类型检查器能直接确认User包含id。
解决方案:给泛型添加类型约束
通过给泛型参数T添加约束,确保所有传入的领域模型都包含id属性,有两种常见方式:
方式1:定义基础领域模型接口
// 定义所有领域模型必须实现的基础接口 interface DomainBase { id: string | number; } // 让User接口继承这个基础接口 interface User extends DomainBase { name: string; } // 泛型抽象类添加约束:T必须继承DomainBase abstract class AbstractModel<T extends DomainBase> extends Model { abstract mapFromDB(): T; abstract mapToDB(domain: T): void; } class UserDetailModel extends AbstractModel<User> { mapFromDB(): User { return new UserInstance(this.id, this.name); } mapToDB(domain: User): void { this.id = domain.id; // 不再报错 this.name = domain.name; } }
方式2:直接在泛型中写约束
如果不需要单独定义基础接口,也可以直接在泛型参数中指定约束:
abstract class AbstractModel<T extends { id: string | number }> extends Model { abstract mapFromDB(): T; abstract mapToDB(domain: T): void; } // User接口保持原样即可 interface User { id: string; name: string; } class UserDetailModel extends AbstractModel<User> { // ... 实现方法不再报错 }
原理说明
添加泛型约束后,TypeScript会明确知道所有传入AbstractModel的T类型都必然包含id属性,因此在实现mapToDB方法时,访问domain.id会被类型检查器认可,解决了ts(2339)错误,同时也保证了所有继承AbstractModel的具体类都只能传入符合约束的领域模型,避免后续出现类似问题。
内容的提问来源于stack exchange,提问作者MoebiusCorzer
相关产品推荐
相关产品推荐

