我有一组对象,每个对象都有自己的属性:
const a = { a1 : 1, a2 : 2 } as const
const b = { b1 : `1`, b2 : `2` } as const
函数f
将所有这些对象作为类型元组:
function f<
T extends { [key : string] : any }[]
> (
...t : [...{ [i in keyof T] : T[i] }]
) {
// todo
}
f(a, b)
目标是返回任何这些对象的任何属性。
在这种情况下,预期结果应该是 1 | 2 | "1" | "2"
.
问题是我不知道如何正确描述返回类型。
我已经尝试过T[number][keyof T[number]]
但它失败了,可能是由于 T
的索引可能存在差异和keyof T
.
然后我为它写了一个包装器:
type PropertyOf<T extends { [key : string] : any }> = T[keyof T]
并指定f
的返回类型如PropertyOf<T[number]>
。但还是不行。
尽管PropertyOf
预期返回1 | 2
对于 PropertyOf<{ a1 : 1, a2 : 2 }>
,当用作 PropertyOf<T[number]>
时在f
函数返回类型为never
.
这是什么原因以及如何解决? 谢谢。
最佳答案
您可以使用这种方法:
declare function f<T extends object[]>(
...t: T
): { [I in keyof T]: T[I][keyof T[I]] }[number]
请注意
object
对于来电者来说通常比{ [key : string] : any }
更宽容因为后者的索引签名阻止您传入interface
的值类型;请参阅ms/TS#15300 .请注意您的输入类型
[...{ [i in keyof T] : T[i] }]
与T
没有区别用于休息参数。
但重要的是,我们是mapping over the T
tuple type并计算你的 PropertyOf<T>
为每个元组元素键入(根据 Is there a `valueof` similar to `keyof` in TypeScript? 也称为 ValueOf<T>
),然后 indexing into生成的元组 number
,结果是 union该元组中的所有类型。
让我们测试一下:
const a = { a1: 1, a2: 2 } as const
const b = { b1: `1`, b2: `2` } as const
const ret = f(a, b);
// const ret: 1 | 2 | "1" | "2"
看起来不错。
关于typescript - 合并 TypeScript 中对象元组的值类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73040062/