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

TypeScript:如何为类添加对应字符串联合类型的属性以实现DRY?

解决方案:实现DRY原则的TypeScript类属性与类别管理

首先,我们要解决两个核心需求:

  • 避免重复维护Category类型和categories数组
  • 让类自动拥有Category中所有类别的属性,无需手动声明每个属性

步骤1:用单一来源管理类别(消除重复)

我们可以用const对象或枚举来作为类别的单一真实来源,这样类型和运行时数组都从这里派生,完全符合DRY原则。

方案A:使用const对象(推荐,更灵活)

// 单一来源:定义所有类别,运行时可用
const CATEGORY_MAP = {
  people: 'people',
  projects: 'projects',
  topics: 'topics',
  tools: 'tools'
} as const;

// 从对象键自动生成联合类型,无需手动写`'people' | 'projects'...`
export type Category = keyof typeof CATEGORY_MAP;

// 自动生成categories数组,完全依赖CATEGORY_MAP,不用重复写
const categories: Category[] = Object.keys(CATEGORY_MAP) as Category[];

方案B:使用枚举

如果更喜欢枚举的语法,也可以这样:

enum Category {
  People = 'people',
  Projects = 'projects',
  Topics = 'topics',
  Tools = 'tools'
}

// 从枚举值自动生成数组
const categories = Object.values(Category);

步骤2:实现类的自动属性赋值

接下来,我们需要让类实现IPostEntryIndex接口,同时无需手动声明每个类别属性。这里利用TypeScript的索引签名和构造函数赋值来实现:

// 假设你的Entry接口定义如下
interface Entry {
  id: string;
  // 示例构造函数
  constructor() {
    this.id = crypto.randomUUID();
  }
}

// 索引类型保持不变(或用Record<Category, Entry>简化)
type IPostEntryIndex = Record<Category, Entry>;

class PostEntryIndex implements IPostEntryIndex {
  // 索引签名允许我们在构造函数中动态赋值属性
  [key: string]: Entry;

  constructor() {
    // 遍历categories数组,为每个类别创建Entry实例
    categories.forEach(cat => {
      this[cat] = new Entry();
    });
  }
}

额外优化:严格类型检查(可选)

上面的实现中,TypeScript允许通过任意字符串键访问类的属性(因为索引签名是string)。如果想要严格限制只能访问Category中的键,可以通过类型断言或工具类型来约束:

// 定义严格类型,移除通用字符串索引,只保留Category的键
type StrictPostEntryIndex = Omit<PostEntryIndex, string> & IPostEntryIndex;

// 创建实例时断言为严格类型
const index = new PostEntryIndex() as StrictPostEntryIndex;

// 正确访问
console.log(index.people.id);

// 错误:TypeScript会报错,因为"nonexistent"不在Category中
// console.log(index.nonexistent);

为什么这符合DRY原则?

  • 新增类别时,只需要修改CATEGORY_MAP(或枚举),Category类型、categories数组、类的属性会自动更新
  • 无需手动在类中声明每个类别属性,构造函数会自动完成赋值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:52:32