typescripttypescript-typingsunion-typesgeneric-type-argument

Array<Union of type>to Array<Union of generic type>


I'm trying to define the relationship between two array type, related by a Wrapper generic type:

interface WrapperType<T> {
  innerValue: T;
}

type InnerArrayType = (TypeA | TypeB | TypeC)[];
type WrappedArrayType = (WrapperType<TypeA>|WrapperType<TypeB>|WrapperType<TypeC>)[];

However, the information between the two union types. When one of them changes, the other one must be manually changed as well. I wonder if there is a reusable utility type that can take the InnerArrayType and the WrapperType and output WrappedArrayType.

type MagicUtility<T> = ???????

type WrappedArrayType = MagicUtility<InnerArrayType>;
// equivalent to
type WrappedArrayType = (WrapperType<TypeA>|WrapperType<TypeB>|WrapperType<TypeC>)[];

In my use case, the list of TypeA, TypeB, TypeC... is predefined, static, and finite. Note that they are NOT string types.

UPDATE

I was able to get Array<Generic of union> with the method below. So there is a way to convert Array<Generic of union> to Array<Union of generic>, the problem would be solved. However, it seems to be an impossible problem: https://github.com/Microsoft/TypeScript/issues/27272.

interface MyWrapper<T> {
    inner: T;
}

type ArrayOfUnionToArrayOfUnionOfGeneric<T> = 
  T extends (infer U)[]
  ? MyWrapper<U>[]
  : never;

type Inner = (1 | 2 | 3)[];
type Outer = ArrayOfUnionToArrayOfUnionOfGeneric<Inner> // MyWrapper<1 | 2 | 3>[]

// MyWrapper<1 | 2 | 3>[] --(HOW???)--> (MyWrapper<1>|MyWrapper<2>|MyWrapper<3>)[]

Solution

  • This is possible using a distributive conditional type: the U extends infer V part is what distributes over the union.

    type MagicUtility<T extends any[]> =
      (T extends (infer U)[] ? U extends infer V ? WrapperType<V> : never : never)[]
    

    Playground Link