从键和值的两个数组/元组创建动态对象类型

问题描述 投票:0回答:1

我有一个键数组和一个值类型元组。

const keys = ["name", "age", "isAlive"] as const;
type Values = [string, number, boolean];

如何使用它们动态构造以下类型?

type DesiredType = {
   name: string;
   age: number;
   isAlive: boolean;
}

我已经尝试过:

const keys = ["name", "age", "isAlive"] as const;
type Values = [string, number, boolean];

type ObjFromArrays<T extends readonly string[], K extends any[]> = {
  [index in T[number]]: K[number];
};

type DesiredType = ObjFromArrays<typeof keys, Values>;

但是它不起作用,因为它在

T
上迭代,但不在
K
上迭代。

arrays typescript object tuples
1个回答
0
投票

本质上,您希望

ObjFromArrays<K, V>
采用相同形状的两种数据类型,其中第一个
K
保存键,第二个
V
保存值,并且您希望将它们连接到单个对象类型中,其中每个键与每个值配对。实现此操作的方法是在 I 数据类型的相关索引
K
上编写
映射类型
,并使用 键重新映射
K[I]
用作键,并将
V[I]
用作值。 假设
K
是一个 tuple 类型,那么相关索引就是
K
对应于元组中位置的类似数字的字符串键。也就是说,如果
K
看起来像
["name", "age", "isAlive"]
,那么我们要迭代的索引就是
"0" | "1" | "2"

我们的实现方式如下:

type ObjFromArrays<
  K extends readonly string[], 
  V extends Record<keyof K, any>
> = {
    [I in `${number}` & keyof K as K[I]]: V[I];
};

这里

K
已被 constrained 为(只读)字符串数组,而
V
已被限制为与
K
具有相同的索引。您也可以V extends readonly string[]
,但是您需要在实现内部检查 
I
 的每个索引 
K
 也是 
V
 的有效索引,如果不是,则执行某些操作。  我们希望防止 
["name", "age", "isAlive"]
 出现 
K
 以及 
[string]
 出现 
V
 之类的情况,其中索引不匹配。相反,通过限制 
Record<keyof K, any>
,我们基本上要求 
V
 至少具有与 
K
 相同的索引。

映射类型迭代

K

 (
keyof K
) 的键,这些键也是 (
&
) 类似数字的字符串。 (
`${number}`
)。我与
`${number}`相交
的原因是为了避免迭代所有类似数组类型的明显键,例如
"length"
"reduce"
"forEach"
等。对于每个这样的键
I
,键输出类型为 
K[I]
,值为 
V[I]

让我们测试一下:

const keys = ["name", "age", "isAlive"] as const; type Values = [string, number, boolean]; type DesiredType = ObjFromArrays<typeof keys, Values>; /* type DesiredType = { name: string; age: number; isAlive: boolean; } */
看起来不错。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.