0

In typescript, an array can be converted to tuple by

type Arr = any[];
const f = < T extends Arr > (...args: [...T]): [...T] => {
  return args;
}

const a = f(1, 'a'); // a is type of [number, string].

We can also map type by

type TypeMap = {
    'n': number;
    's': string
};

const g = <T extends keyof TypeMap>(args: T): TypeMap[T] => {
    throw null;
}

const b = g('s'); //b is type of string

How can I combine above two requirements into one? I tried

const h = <T extends keyof TypeMap>(...args: [...T[]]): [...TypeMap[T][]] => {
    throw null;
}
const c = h('s', 'n');

However, c is type of (string|number)[] instead of [string, number]. I tried

const h = <T extends (keyof TypeMap)[]>(...args: [...T]): [...TypeMap[T[number]][]] => {
    throw null;
}

but got the same c.

I found a solution using object instead of tuple, but tuple solution are welcome.

const f1 = <T extends keyof TypeMap>(...args: [...T[]]): {[P in T]: TypeMap[P]} => {
    throw null;
}
const {s, n} = f1('s', 'n');

typescript playground

1 Answer 1

1

You want to use a mapped tuple. Given T, a tuple type, {[I in keyof T]: ...T[I]...} will be another tuple type; the I only iterates over numeric indices of T. Note that due to a bug/limitation in TypeScript (see microsoft/TypeScript#27995) the compiler doesn't realize that T[I] will be the element type of T, so you have to use some trick like the Extract utility type.

In your case, from the input tuple T extending Array<keyof TypeMap>, you want the output tuple to have an element of type TypeMap[T[I]] at numeric index I:

const h = <T extends (keyof TypeMap)[]>(...args: [...T]): {
    [I in keyof T]: TypeMap[Extract<T[I], keyof TypeMap>]
} => {
    throw null;
}

const c = h('s', 'n'); // [string, number] 

Playground link to code

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.