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

如何为TypeScript泛型Entity类实现基于Omit的类型定义?

解决Prisma模型泛型包装类的受保护属性问题

核心问题是你需要让泛型类同时捕获模型类型和受保护属性的联合类型,而非依赖实例属性推导类型——因为实例属性的类型无法直接用于Omit的类型计算。下面是具体解决方案:

方案:添加第二个泛型参数

把受保护属性的联合类型作为显式泛型参数传入类定义,这样就能直接在Omit中使用该类型,同时保证类型安全:

type User = {
  user_id: bigint;
  password: string;
  email_address: string;
};

// 泛型类接收两个参数:模型类型T,受保护属性联合类型K(约束为T的键子集)
class Entity<T, K extends keyof T> {
  protected protectedProps: K[];
  private data: T;

  constructor(data: T, protectedProps: K[]) {
    this.data = data;
    this.protectedProps = protectedProps;
  }

  // 返回自动排除受保护属性的类型化数据
  getPublicData(): Omit<T, K> {
    const publicData = {} as Omit<T, K>;
    for (const key in this.data) {
      if (!this.protectedProps.includes(key as K)) {
        publicData[key as Exclude<keyof T, K>] = this.data[key];
      }
    }
    return publicData;
  }
}

// 使用示例
const userData: User = {
  user_id: BigInt(1),
  password: "secret123",
  email_address: "user@example.com",
};

// 显式传入受保护属性联合类型,IDE会自动补全合法键
const userEntity = new Entity(userData, ['user_id', 'password']);
// getPublicData返回类型为Omit<User, 'user_id' | 'password'>,仅包含email_address
console.log(userEntity.getPublicData());

为什么之前的写法报错?

你之前尝试定义protectedProps: (keyof User)[],但T["protectedProps"]是去读取模型类型T中名为protectedProps的属性,而非你定义的类属性的类型。通过添加泛型参数K,我们把受保护属性的联合类型直接传递给TypeScript,让它能正确计算Omit后的结果,同时解决了keyof T[]与keyof T不兼容的问题。

优化:设置默认受保护属性

如果大部分模型有通用的受保护属性(比如id、password),可以给泛型参数K设置默认值,简化使用:

// 默认排除以_id结尾的属性和password(如果模型包含这些键)
class Entity<T, K extends keyof T = 'password' | keyof T & `${string}_id`> {
  protected protectedProps: K[];
  private data: T;

  constructor(data: T, protectedProps?: K[]) {
    this.data = data;
    // 如果没传受保护属性,用默认的键数组
    this.protectedProps = (protectedProps || (['password', ...Object.keys(data).filter(k => k.endsWith('_id'))] as K[]));
  }

  getPublicData(): Omit<T, K> {
    // 实现逻辑同上
    const publicData = {} as Omit<T, K>;
    for (const key in this.data) {
      if (!this.protectedProps.includes(key as K)) {
        publicData[key as Exclude<keyof T, K>] = this.data[key];
      }
    }
    return publicData;
  }
}

// 使用时可省略受保护属性参数,自动应用默认规则
const userEntity = new Entity(userData);

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:40:32