Home > other >  Typescript - get one type from generic union type of rest parameters
Typescript - get one type from generic union type of rest parameters

Time:11-11

I have some union, generic class, and generic function

type SomeUnion = "first" | "second" | "third"

class SomeClass<TypeFromUnion extends SomeUnion>{}

function someFn<A extends SomeUnion, B extends SomeUnion>(a: SomeClass<A>, b:SomeClass<B>) {}

For call

someFn(new SomeClass<"first">(), new SomeClass<"second">())

inside the function, a processes as SomeClass<"first">, b as SomeClass<"second">. Exactly the types I need.

But I need the function to be with rest parameters. Something like:

function someFn<T extends SomeUnion>(...rest: SomeClass<T>[]) {}

With the same function call, now rest[0] processes as SomeClass<"first" | "second">. I understand why this happens, but I need the type of rest[0] to be processed as SomeClass<"first">, rest[1] as SomeClass<"second"> and so on. Otherwise it breaks my next type inference. How can I achieve what I need?

The calls are expected to be like:

someFn(new SomeClass<"first">())
someFn(new SomeClass<"third">(), new SomeClass<"second">())
someFn(new SomeClass<"third">(), new SomeClass<"first">(), new SomeClass<"second">())

CodePudding user response:

I think you need a tuple, not an array type, to separate each element of the rest generic type. Then you could use a mapped tuple type to map each one to the corresponding SomeClass

type SomeUnion = "first" | "second" | "third"

class SomeClass<TypeFromUnion extends SomeUnion>{}

function someFn<T extends [...SomeUnion[]]>(...rest: {[K in keyof T]: SomeClass<T[K]>}): typeof rest {
    return rest;
}

let vs = someFn(new SomeClass<"first">(), new SomeClass<"second">(), new SomeClass<"third">())
//  ^?let vs: [SomeClass<"first">, SomeClass<"second">, SomeClass<"third">]

playground

  • Related