简体   繁体   English

Typescript 数组中通用参数的并集

[英]Typescript union of generic parameters in array

I have an interface with three generic parameters that looks something like this我有一个带有三个通用参数的接口,看起来像这样

interface X<A,O,I> {
...
}

I want to create a function that accepts an array of these interfaces as a rest argument such that the types of O and I are the same, but the type of A can vary.我想创建一个 function 接受这些接口的数组作为 rest 参数,这样 O 和 I 的类型相同,但 A 的类型可以不同。 Additionally, I want the return type to be a union of all the types of A.此外,我希望返回类型是 A 的所有类型的联合。

let item1: X<Type1,string,string> = value1;
let item2: X<Type2,string,string> = value2;

// I want the return type for this to be 'Type1 | Type2'
myFunction(item1, item2) 

I've been thinking about this for a while and can't come up with anything good.我一直在考虑这个问题,想不出什么好办法。 Wondering if anyone else has a better thought on how to accomplish this.想知道是否还有其他人对如何实现这一目标有更好的想法。

EDIT: Based on wantok's answer, I ended up with this编辑:根据 wantok 的回答,我最终得到了这个

type ExtractFirst<T> = T extends X<infer A, unknown, unknown>[] ? A : never;

export function myFunction<T extends Array<X<any, unknown, I>>, I>(input: I, ...types: T): ExtractFirst<T> {
  ...
}

I don't know whether I understood you properly, or I'm dumb but it's really simple from my point of view:D我不知道我是否理解正确,或者我很笨,但从我的角度来看它真的很简单:D

const myFunction (item1: Item1Interface, item2: Item2Interface): Type1 | Type2 => {}

Or if you want to "dynamically" read the type from your function parameter I hope you can do something like this:或者,如果您想“动态地”从 function 参数中读取类型,我希望您可以这样做:

const myFunction (item1: Item1Interface, item2: Item2Interface): typeof item1 => {}
interface X<A, O, I> {
    getA(): A;
}
// The other generic types of X don't have to be unknown, but they
// need to be something.

function myFunction<T>(...items: Array<X<T, unknown, unknown>>): T {
    return items[0].getA();
}
const item1: X<string, string, string> = { ... };
const item2: X<number, string, string> = { ... };

const v = myFunction(item1, item2); // This doesn't compile.
// Argument of type 'X<number, string, string>' is not assignable to
// parameter of type 'X<string, unknown, unknown>'.
//  Type 'number' is not assignable to type 'string'.

const v = myFunction<string | number>(item1, item2); // This does compile.

If the types of A on the different items are not the same, you need to tell the function which types you're passing.如果不同项目上的A类型不相同,则需要告诉 function 您传递的是哪种类型。 In practice, this shouldn't be a big deal, since you will either be constructing your items manually and thus, you should know the union you'll need to pass, or you got the list of items from somewhere else in which case you must already have a type that they all conform to.实际上,这应该没什么大不了的,因为您要么手动构建项目,因此,您应该知道需要传递的联合,或者您从其他地方获得项目列表,在这种情况下,您必须已经有一个它们都符合的类型。

You can also use a conditional type to extract the union type if you have an array of items.如果您有一个项目数组,您还可以使用条件类型来提取联合类型。

type ExtractFirst<T> = T extends X<infer A, unknown, unknown>[] ? A : never;
const args = [item1, item2];

// equivalent to myFunction<string | number>(..args);
const v = myFunction<ExtractFirst<typeof args>>(...args);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM