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

如何将对象的键作为TypeScript联合类型约束函数参数?

解决方案:让TypeScript自动约束函数参数为对象的键

这个问题的核心是要保留对象的精确类型信息,同时让TypeScript自动推导键的联合类型,不用每次修改对象都手动更新类型约束。我们可以通过两个关键调整来解决:


1. 修正对象的类型定义,保留精确的键信息

你之前的代码里用as {[key: string]: number}做了类型断言,这直接抹掉了TypeScript对obj具体键的推断能力。去掉这个断言,让TypeScript自动推导对象的只读字面量类型:

// 去掉不必要的类型断言,让TypeScript自动推断精确类型
const obj = Object.freeze({ 'hello': 64, 'world': 20 });
// 此时 typeof obj 是 Readonly<{ hello: number; world: number }>

2. 改造pick函数,用keyof typeof动态约束参数

利用TypeScript的keyof操作符,结合typeof obj获取对象的键联合类型,把这个类型作为keys数组的元素类型。这样不仅编译时会检查传入的键是否合法,而且当你修改obj的键时,这个约束会自动同步更新:

const pick = (keys: Array<keyof typeof obj>): Array<number> => {
  const values = [];
  for (const key of keys) {
    // 运行时检查依然保留,应对可能绕过编译检查的场景
    if (!(key in obj)) {
      throw new Error(`There's no such key: ${key}`);
    }
    values.push(obj[key]);
  }
  return values;
};

测试效果

现在TypeScript会在编译阶段直接拦截无效键:

// 编译通过,完全合法
pick(['hello', 'world']);

// 编译报错:类型'"test"'的参数不能赋给类型'"hello" | "world"'的参数
pick(['test']);

进阶优化:让返回值类型更精确

如果想让函数返回值的类型更贴合实际值(比如返回Array<64 | 20>而非Array<number>),可以用泛型结合索引访问类型:

const pick = <K extends keyof typeof obj>(keys: Array<K>): Array<typeof obj[K]> => {
  const values: Array<typeof obj[K]> = [];
  for (const key of keys) {
    if (!(key in obj)) {
      throw new Error(`There's no such key: ${key}`);
    }
    values.push(obj[key]);
  }
  return values;
};

// 此时 pick(['hello']) 的返回类型是 Array<64>,pick(['hello', 'world']) 是 Array<64 | 20>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:49:33