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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:25:23