我想创建具有可选类型参数数量的函数。例如,函数接受参数,其中每个参数都是数组并返回数组,其中第 n 项是第 n 个参数中的随机项:
const getRandomItems<T1, T2, T3>(...arrays: [T1[], T2[], T3[]]): [T1, T2, T3] = {
const result = []
for (const items of arrays) {
result.push(items[Math.floor(Math.random() * items.length)])
}
return result
}
const fruits = ['Apple', 'Orange', 'Banana']
const colors = ['Red', 'Green', 'Blue']
const cars = [new Car('Ferrari'), new Car('Porsche')]
// E.g. ['Apple', 'Blue', new Car('Porsche')]
getRandomItems<string, string, Car>(friuts, colors, cars)
// E.g. ['Orange', new Car('Ferrari'), 'Red']
getRandomItems<string, Car, string>(friuts, cars, colors)
该函数接受 3 个参数并返回具有 3 个参数的数组。但是我可以创建函数吗:
- 接受任意数量的类型化参数,例如。 G。
<T1, T2, T3, T4>
, - 接受与类型参数相同数量的参数:
...arrays: [T1[], T2[], T3[], T4[]]
, - 返回与类型参数相同类型的数组:
[T1, T2, T3, T4]
?
// Something like this:
const getRandomItems<...T>(...arrays: [...T[]]): [...T] = {
}
最佳答案
您需要使用 mapped type循环输入的类型并将每个数组类型转换为其元素的类型:
type UnwrapArray<T> = T extends (infer U)[] ? U : T;
type Result<T extends any[][]> = {
[I in keyof T]: UnwrapArray<T[I]>;
}
function getRandomItems<T extends any[][]>(...arrays: T): Result<T> {
const result = []
for (const items of arrays) {
result.push(items[Math.floor(Math.random() * items.length)])
}
return result as any;
}
首先,我们需要一个辅助类型 UnwrapArray
从数组中提取元素的类型。请参阅this SO answer了解更多信息。
接下来,我们得到函数返回值的类型。它采用类型 T
这是一个双重嵌套数组,迭代所有键 [I in keyof T]
(因为这是一个数组,所以键是索引)并提取每个数组的元素类型 UnwrapArray<T[I]>
.
最后,该函数只接受一个通用参数 T
具有与 Result
相同的约束。这样,提供多少个参数并不重要。
注意:需要将结果转换为 any
在函数体内部,因为编译器对 Result<T>
没有足够高的理解事实上是。
关于javascript - TypeScript 中类型参数的可选计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57852373/