是否有如下Map类型的方法:
type ObjectType = {
prop1: number;
prop2: string;
prop3: boolean;
prop4: string;
};
到以下内容?
type TupleType = [number, string, boolean, string]
我在第一次将ObjectType
类型的对象转换为Object.values
类型的数组时运气不佳,结果数组的类型将计算为(string | number | boolean)[]
,这不是元组类型,只是一个联合类型的数组。
从注解中我了解到,如果对象在最初定义后被修改,属性的顺序可能会改变,在这种情况下,我也可以使用Map
。
另一种可能的解决方案是使用如下所示的元组数组作为基础,以确保顺序不会改变:
type TupleListType = [
[string, number],
[string, string],
[string, boolean],
[string, string],
];
const argsTupleList: TupleListType = [
["prop1", 1],
["prop2", "two"],
["prop3", true],
["prop4", "four"],
]
如果我有办法将argsTupleList
转换为[number, string, boolean, string]
类型的数组,这个问题也会得到解决。
结果数组需要具有该类型,因此我可以将其传递给带有spread运算符的函数,如someFunc(...argsTuple)
。
如果我只是把对象转换成一个Object.values(args)
的数组,我会得到:
spread参数必须具有元组类型或传递给rest参数。ts(2556)
重构函数以接受不同格式的args并不是我要找的。
2条答案
按热度按时间xtfmy6hx1#
基于共享的最小repro,我编写了一个函数,它只是以类型安全的方式转换结构。
Playground
i34xakig2#
为了避免试图让TypeScript编译器知道或关心对象类型中的属性顺序的问题(对象类型很多;
keyof
将产生一个union,它的顺序是由实现定义的,所以你可以从中得到一些东西,但是它可能与你期望的不同;有关更多信息,请参见How to transform union type to tuple type),我们将探索"另一种可能的解决方案",它使用元组的元组作为开始,而不是对象类型。我们需要一个像
argsTupleListToTupleType()
这样的函数,它接受一个类型为键-值对数组的输入(每个键-值对的第一个元素都有一个类似键的类型),并将其转换为一个只包含值的数组。该函数是输出类型
T
中的generic,并且argsTupleList
输入参数是T
上的Map元组类型,其中T
的每个元件已经被readonly
对代替,该readonly
对具有键状第一元件和作为第二元件的来自T
的元件。(注意,readonly
元组比非readonly
元组接受 * 更多 * 输入,所以这更容易适应。)由于这是一个 * 同态 * Map类型(参见What does "homomorphic mapped type" mean?),编译器能够从Map类型的输入值 * 推断 *T
。还要注意的是,我将
argsTupleList
的类型设置为readonly
可变元组类型,因此readonly [...XXX]
而不仅仅是XXX
,这给了编译器一个提示,提示它应该尽可能将argsTupleList
解释为元组类型,并且它应该接受任何const
Assert的输入。本质上,这种 Package 只是使函数更适应以不同的方式被调用,而不真正改变基本操作。这就是类型系统,那么实现呢?这是一个使用the
map()
array method的简单的argsTupleList.map(x => x[1])
。TypeScript编译器不可能验证它是否满足调用签名,所以我们需要使用一个类型Assert来告诉它我们已经自己完成了检查,它不应该担心。(更多信息请参见Mapping tuple-typed value to different tuple-typed value without casts):让我们用你的例子来试试:
看起来不错。
tuple
的类型和值都是我们所期望的。这也适用于不同的输入:Playground代码链接