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

TypeScript中如何遍历只读数组并维持数组项类型

解决方案:类型安全地创建键为指定数组元素的Map

问题根源

原代码中,泛型Buttons被约束为ReadonlyArray<string | number>,导致buttonPin的类型被拓宽为string | number;而ArrayValues<Buttons>实际是数组元素的具体联合类型(比如传入['a', 1]时是'a' | 1),两者类型不兼容,因此需要手动断言,存在出错风险。

优化方案

方案1:调整泛型约束,让元素类型精确匹配

通过拆分泛型,明确数组元素的类型V,确保遍历的元素类型和Map键类型完全一致:

function test<V extends string | number>(buttonPins: readonly V[]) {
  const buttonMap = new Map<V, boolean>();

  buttonPins.forEach((buttonPin) => {
    buttonMap.set(buttonPin, true); // 类型完全匹配,无报错
  });

  return buttonMap;
}

// 测试示例:传入字面量数组时,Map键类型会自动推导为精确的联合类型
const buttonMap = test(['power', 10, 'reset']);
// buttonMap 的类型:Map<'power' | 10 | 'reset', boolean>

方案2:利用Map构造函数+数组map方法自动推导类型

直接通过map将数组转换为[键, 值]元组,再传入Map构造函数,结合as const确保类型精确:

function test<Buttons extends ReadonlyArray<string | number>>(buttonPins: Buttons) {
  // 用 map 生成元组数组,as const 固定元组类型,让Map自动推导键类型
  const buttonMap = new Map(buttonPins.map(pin => [pin, true] as const));
  return buttonMap;
}

const buttonMap = test(['up', 5, 'down']);
// buttonMap 的类型:Map<'up' | 5 | 'down', boolean>

方案3:简化自定义类型工具(可选)

你自定义的ArrayValues类型可以用TypeScript内置的索引访问类型T[number]替代,效果完全一致:

// 替代自定义的 ArrayValues<T>
type ArrayValues<T extends ReadonlyArray<unknown>> = T[number];

关键说明

  • 类型断言(as ...)会绕过TypeScript的类型检查,存在注入错误值的风险,应尽量避免。
  • 让数组元素类型和Map键类型保持精确一致是解决问题的核心,通过泛型约束或自动推导都能实现。
  • 使用readonly修饰数组参数,确保输入数组不会被修改,同时帮助TypeScript推导更精确的字面量类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:22:38