Home > other >  tuple mapper function typing
tuple mapper function typing

Time:03-16

I need to type a function that takes a tuple in and outputs a mapped version of it
as a first try I defined an identity tuple that returns a tuple of same type

    declare const tupleIdentity: <Tup extends readonly any[]>(tup: Tup) => Tup
    const [a, b, c, d] = tupleIdentity([1, 's', 3]) // a:number, b:string, c:number, d:undefined

that's great, it tracks tuple's length and elements types !
but couldn't find a typing returning a mapped version of the tuple
e.g. an object wrapping each element

    // a naive attempt :

    type Wrap<T> = { wrapped: T }
    declare const tupleMapper: <Tup extends readonly any[]>(tup: Tup) 
      => Tup extends Array<infer T> ? Wrap<T>[] : never
    const [x, y, z] = tupleMapper([1, 's', 3]) // x,y,z: Wrap<string | number> | undefined

can Ts type system declare such a typing ?

CodePudding user response:

You can declare the type using a mapped type (which yields a tuple when applied to a tuple type):

type Wrap<T> = { wrapped: T }

declare const tupleMapper: <Tup extends readonly any[]>(tup: Tup) => 
  {[K in keyof Tup]: Wrap<Tup[K]>}

const [x, y, z] = tupleMapper([1, 's', 3]) // [Wrap<number>, Wrap<string>, Wrap<number>]
// x: Wrap<number>
// y: Wrap<string>
// z: Wrap<number>

CodePudding user response:

Let's change the mapper function a little first:

declare const map: <T extends ReadonlyArray<unknown>>(tuple: T) => MapTuple<T>;

It takes any tuple and then passes that tuple to a type MapTuple where the real magic happens.

And here it is:

type MapTuple<T, R extends ReadonlyArray<unknown> = []> =
    T extends readonly [infer First, ...infer Rest]
        ? MapTuple<Rest, [...R, Wrap<First>]> : R;

We get the first element of T, as well as the remaining ones as another tuple.

If it isn't able to infer these then the tuple is empty, so we return R, the result.

However if it does, we map the remaining elements, and add to the result, a wrapped first element.

This is basically a loop, mapping over each element.

Playground

  • Related