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

如何在TypeScript中强制字典与字符串数组的键严格匹配?

实现字典键与数组元素的完全匹配约束

需求说明

需要实现一个函数f,接收Record<string, string>类型的字典和字符串数组,要求:

  • 数组中的值必须是字典的键
  • 二者完全一致,即以下两种情况在编译时必须报错:
    1. 字典存在数组未包含的额外键
    2. 数组存在字典未定义的额外元素

合法调用示例:

f({ a: "foo", b: "bar" }, ["a", "b"]);

需要编译报错的调用:

// 字典存在额外键c
f({ a: "foo", b: "bar", c: "baz" }, ["a", "b"]);
// 数组存在额外元素c
f({ a: "foo", b: "bar" }, ["a", "b", "c"]);

已有尝试

校验数组额外元素的方案

该方案通过泛型约束数组元素必须是字典键的子集,能拦截数组多元素的情况:

function f<
    D extends Record<string, string>,
    A extends Array<keyof D> 
>(d: D, a: A): void {
    console.log(d, a);
}

// 数组中的"c"不属于字典键,编译报错
f({ a: "foo", b: "bar" }, ["a", "b", "c"]);

校验字典额外键的方案

通过UnionToIntersection类型将数组元素转为字典的精确键类型,拦截字典多键的情况(注意数组需要用as const断言):

export type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends 
  ((k: infer I) => void) ? I : never;

function f<A extends readonly string[]>(
  d: UnionToIntersection<{ [K in A[number]]: string }>, 
  a: A
): void {
    console.log(d, a);
}

// 字典中的`c: "baz"`不在数组中,编译报错
f({ a: "foo", b: "bar", c: "baz" }, ["a", "b"] as const);

合并后的完整解决方案

将两种约束结合,同时校验数组元素不能超出字典键,且字典键不能超出数组元素:

export type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends 
  ((k: infer I) => void) ? I : never;

function f<
  K extends string,
  A extends readonly K[],
  D extends Record<K, string>
>(
  d: D & UnionToIntersection<{ [Key in A[number]]: string }>,
  a: A
): void {
    console.log(d, a);
}

// 合法调用,无报错
f({ a: "foo", b: "bar" }, ["a", "b"]);

// 情况1:字典存在额外键c,编译报错
f({ a: "foo", b: "bar", c: "baz" }, ["a", "b"]);

// 情况2:数组存在额外元素c,编译报错
f({ a: "foo", b: "bar" }, ["a", "b", "c"]);

方案说明

  1. 泛型A extends readonly K[]结合D extends Record<K, string>,确保数组元素只能是字典D的键,拦截数组多元素的情况。
  2. 参数d的类型D & UnionToIntersection<{ [Key in A[number]]: string }>通过交叉类型实现双向约束:
    • UnionToIntersection<{ [Key in A[number]]: string }>生成仅包含数组元素作为键的精确字典类型
    • 与D交叉后,D不能包含该精确类型之外的键,从而拦截字典多键的情况
  3. 无需手动添加as const断言,TypeScript会自动推导数组的精确字面量类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:31:11