1

Following the question on creating a choice between types Defining a choice of index type on an interface

I now have to create a sequence of elements, usually it can be written as element1 & element2, but since i am converting an XSD schema i want it to be a 1-to-1 match, so that new TypeScript developers won't be confused with what is going on.

Currently i have this type

type Object_Type<T> = { [P in keyof T]: T[P] };
type Sequence<A, B = {}, C = {}, D = {}, E = {}, F = {}, G = {}, H = {}, I = {}, J = {}, K = {}, L = {}, M = {}, N = {}> =
    Object_Type<A>
    & Object_Type<B>
    & Object_Type<C>
    & Object_Type<D>
    & Object_Type<E>
    & Object_Type<F>
    & Object_Type<G>
    & Object_Type<H>
    & Object_Type<I>
    & Object_Type<J>
    & Object_Type<K>
    & Object_Type<L>
    & Object_Type<M>
    & Object_Type<N>;

And can be used like this

const sequence: Sequence<{name: string}, {age: number}> = {
    name: "John",
    age: 999
};

However, it is quite extreme to manually have to define every single generic parameter, and also giving them a default value, so i was wondering if it was possible to define like so

type Sequence<...T> = Object_Type<...T>;
Pavlo
  • 1,157
  • 7
  • 13

1 Answers1

2

There are no explicit variadic kinds in TypeScript, so the exact formulation like Sequence<...T> doesn't work. But you could use a tuple type instead as in Sequence<[{name: string}, {age: number}]>. Given a tuple type you could map it with Object_Type, convert the tuple to a union by looking up its number property, and then convert the union to an intersection.

type Object_Type<T> = { [P in keyof T]: T[P] };
type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type Sequence<T extends any[]> = 
  UnionToIntersection<{ [K in keyof T]: Object_Type<T[K]> }[number]>;

const sequence: Sequence<[{ name: string }, { age: number }]> = {
  name: "John",
  age: 999
};

That works, although there might be some edge cases that differ (e.g., if your individual A, B, etc types are themselves unions). These could likely be hammered out, but... I guess I don't understand the use case here. Object_Type is mostly a no-op, so what are you doing with it? What do you gain by the expression Sequence<A,B,C> (or Sequence<[A,B,C]> in my version) that you don't get by A & B & C? Maybe if you elaborate, there'd be an easier or better solution for what you're trying to do.

jcalz
  • 264,269
  • 27
  • 359
  • 360