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

如何用TypeScript从接口键生成含全部键的元组数组类型?

TypeScript 类型约束:数组需包含所有接口键且键值类型严格匹配

用代码说明需求更直观:

// `type` 或 `interface` 均可
interface MyCollection {
  name: string;
  age: number;
}

// 我目前的实现方案
type List<T> = Array<{ itemkey: keyof T }>;

// 期望:MyCollection 的每个键都作为 myList 项的 itemkey 值
const myList: List<MyCollection> = [
  { itemkey: 'name' },
  { itemkey: 'age' },
];

当前方案仅能实现键的智能提示和错误键拦截,但无法保证MyCollection的每个键都出现在myList中,比如以下不符合需求的写法会被允许:

const myList: List<MyCollection> = [
  { itemkey: 'age' },
];

额外需求:每个条目里的value要严格匹配对应键的类型,现有方案无法拦截类型不匹配的错误:

type List<T> = Array<{ key: keyof T, value: T[keyof T] }>;

// 错误:此处 value 应仅允许 number,但当前接受 string
const myList: List<MyCollection> = [
  { key: 'age', value: 'should be number, not string' },
];

我尝试过映射类型、元组、as重映射等方法均未解决,暂未找到纯TypeScript类型系统的实现方式,感觉用JS迭代实现这类约束会更简单。


解决方案

要同时满足「数组必须包含所有接口键」和「键值类型严格匹配」,可以通过映射类型、联合类型转元组的技巧实现静态约束:

1. 定义单个键值对的强绑定类型

先创建一个类型,确保key和value的类型严格对应,避免类型混用:

type Entry<T, K extends keyof T> = {
  key: K;
  value: T[K];
};

2. 生成所有键对应的条目联合类型

将接口的每个键都转换为对应的Entry类型,形成包含所有可能条目的联合类型:

type AllEntries<T> = { [K in keyof T]: Entry<T, K> }[keyof T];

3. 约束数组必须包含所有条目(无遗漏)

通过联合类型转元组的辅助类型,确保数组包含联合类型的所有成员,实现完整性检查:

// 辅助类型:将联合类型转换为包含所有成员的元组
type UnionToTuple<T> = (
  (T extends any ? (t: T) => T : never) extends (...args: infer U) => any ? U : never
);

// 辅助类型:验证元组包含联合类型的全部成员
type AssertAllMembers<T, U extends T[]> = U[number] extends T ? (T extends U[number] ? U : never) : never;

// 最终的 List 类型
type List<T> = AssertAllMembers<AllEntries<T>, UnionToTuple<AllEntries<T>>>;

使用示例

interface MyCollection {
  name: string;
  age: number;
}

// ✅ 合法:包含所有键,且值类型匹配
const myList: List<MyCollection> = [
  { key: 'name', value: 'Alice' },
  { key: 'age', value: 30 },
] as const;

// ❌ 错误:缺少 'name' 条目
const myList2: List<MyCollection> = [
  { key: 'age', value: 30 },
] as const;

// ❌ 错误:value 类型不匹配
const myList3: List<MyCollection> = [
  { key: 'age', value: '30' },
  { key: 'name', value: 30 },
] as const;

说明

  • 必须使用as const让TypeScript推断出精确的元组类型,否则数组会被推断为联合类型数组,无法触发完整性检查。
  • 元组顺序不固定,若需要固定顺序(与接口键顺序一致),可基于TypeScript 4.1+的按键遍历特性修改UnionToTuple实现。
  • 该方案完全通过TypeScript类型系统实现静态约束,无需运行时代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:35:27