简体   繁体   中英

Typescript function signature that converts an array to tuple of mapped type

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM