Reputation: 6854
I have the following function:
const data = {
id: 1,
name: '',
}
type keysType = keyof(typeof data);
function getKeysValues(...keys: keysType[]) {
return keys.map(k => data[k]);
}
const value = getKeysValues('id', 'name');
The type of value
is (string | number)[]
. How can I change it to be dynamic based on the passed keys? So, in the above case I'm expecting the type to be [number, string]
.
Upvotes: 3
Views: 7212
Reputation: 8520
The simplest way to go:
function getKeysValues(...keys: Array<keyof typeof data>): Array<typeof data[keyof typeof data]> {
return keys.map(k => data[k]);
}
You may also add generics:
function getKeysValues<K extends keyof typeof data>(...keys: Array<K>): Array<typeof data[K]> {
return keys.map(k => data[k]);
}
But for convenience in any of the above cases I would type-aliased the typeof data
type Data = typeof data;
// then
function getKeysValues(...keys: Array<keyof Data>): Array<Data[keyof Data]>;
// or
function getKeysValues<K extends keyof Data>(...keys: Array<K>): Array<Data[K]>;
Upvotes: 1
Reputation: 1494
Use mapped types on tuples TypeScript 3.1
const data = {
id: 1,
name: '',
}
type Data = typeof data;
type DataKeysType = keyof(typeof data);
type DataFieldType<T> = T extends DataKeysType ? Data[T] : never;
type MappedDataTuple<T extends DataKeysType[]> = {
[K in keyof T]: DataFieldType<T[K]>;
}
function getKeysValues<T extends DataKeysType[]>(...keys: T): MappedDataTuple<T> {
return <any>keys.map(k => data[k]);
}
// const value: [number, string]
const value = getKeysValues('id', 'name');
Upvotes: 4