更新:从 TS3.1 开始,下面的答案已过时。我相信你现在可以使用映射元组类型 and 条件类型推断得到你想要的行为:
type ExtractValue<T extends ReadonlyArray<SomethingWithAValue<any>>> =
{ [K in keyof T]: T[K] extends SomethingWithAValue<infer V> ? V : never };
function collect<T extends ReadonlyArray<SomethingWithAValue<any>>>(
array: T
): () => ExtractValue<T> {
return () => array.map(a => a.value) as any;
}
让我们使用它...首先让我们通过辅助函数轻松获取元组类型tuple()
它接受可变数量的参数并输出一个元组(从 TS3.0 开始这已成为可能)
type Narrowable = string | number | boolean | undefined | null | void | {};
const tuple = <T extends Narrowable[]>(...t: T) => t;
让我们看看它是否有效:
const result = collect(tuple({ value: 10 }, { value: "hey" }, { value: true }));
// const result: () => [number, string, boolean]
看起来不错!
旧答案:
没有可变参数类型在 TypeScript 中,因此无法输入通用元组(与语法不同[T...]
存在)。
作为解决方法,您可以为任意长度的元组提供函数重载,直到某个合理的最大值:
function collect<A, B, C, D, E>(array: [SomethingWithAValue<A>, SomethingWithAValue<B>, SomethingWithAValue<C>, SomethingWithAValue<D>, SomethingWithAValue<E>]): () => [A, B, C, D, E];
function collect<A, B, C, D>(array: [SomethingWithAValue<A>, SomethingWithAValue<B>, SomethingWithAValue<C>, SomethingWithAValue<D>]): () => [A, B, C, D];
function collect<A, B, C>(array: [SomethingWithAValue<A>, SomethingWithAValue<B>, SomethingWithAValue<C>]): () => [A, B, C];
function collect<A, B>(array: [SomethingWithAValue<A>, SomethingWithAValue<B>]): () => [A, B];
function collect<A>(array: [SomethingWithAValue<A>]): () => [A];
function collect<T>(array: SomethingWithAValue<T>[]): () => T[] {
// implementation
}
这应该适用于长度最大为 5 的元组,并且您可以在顶部添加其他重载以满足实践中您需要的任何内容。它既冗长又丑陋,但应该可以工作。
希望有帮助;祝你好运!