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

TypeScript如何实现ReadonlyArray<IProduct>的id属性唯一且不引入额外框架

解决方案

因为数组仅会一次性创建、后续不会修改,不需要额外引入第三方框架,以下是两种适配不同场景的原生实现方案:

方案1:运行时校验/去重(适用动态生成的产品列表)

通过Set记录已出现的id,在生成只读数组阶段完成去重,也可以根据需求遇到重复id直接抛出错误提前终止:

interface IProduct {
  id: number;
  name: string;
  price: number;
  description?: string;
}

function createUniqueProductArray(products: IProduct[]): ReadonlyArray<IProduct> {
  const existedIds = new Set<number>();
  const uniqueProducts: IProduct[] = [];

  for (const product of products) {
    if (existedIds.has(product.id)) {
      // 严格校验场景下直接抛错,不需要去重可开启下行注释
      // throw new Error(`产品id重复: ${product.id}`);
      continue;
    }
    existedIds.add(product.id);
    uniqueProducts.push(product);
  }

  // 冻结数组保证完全只读,无法后续增删改
  return Object.freeze(uniqueProducts);
}

// 使用示例
const readonlyProducts = createUniqueProductArray([
  { id: 1, name: "笔记本", price: 5999 },
  { id: 2, name: "手机", price: 3999 },
  { id: 1, name: "重复的笔记本", price: 5899 } // 该条会被自动过滤
]);

方案2:编译期静态校验(适用代码内写死的常量列表)

如果你的产品数组是直接硬编码在代码里的常量,可以用TS类型实现编译期的id重复校验,不需要等到运行时就能发现问题:

interface IProduct {
  id: number;
  name: string;
  price: number;
  description?: string;
}

// 类型层面判断id是否重复
type CheckDuplicateId<T extends IProduct[], UsedIds = never> = 
  T extends [infer First extends IProduct, ...infer Rest extends IProduct[]]
    ? First["id"] extends UsedIds
      ? `重复的产品id: ${First["id"]}`
      : CheckDuplicateId<Rest, UsedIds | First["id"]>
    : never;

// 静态常量定义工具
function defineConstProductList<
  T extends readonly IProduct[]
>(list: CheckDuplicateId<[...T]> extends never ? T : CheckDuplicateId<[...T]>): ReadonlyArray<IProduct> {
  return Object.freeze(list);
}

// 无重复时编译正常
const validList = defineConstProductList([
  { id: 1, name: "键盘", price: 299 },
  { id: 2, name: "鼠标", price: 199 },
] as const);

// 有id重复时编译直接报错,提示「不能将类型“"重复的产品id: 1"”分配给类型“never”」
const invalidList = defineConstProductList([
  { id: 1, name: "键盘", price: 299 },
  { id: 1, name: "重复键盘", price: 279 },
] as const);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:45:08