Typescript推断返回的数组类型元素

3

我有以下函数:

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');
value的类型为(string | number)[]。如何根据传递的密钥动态更改它的类型?因此,在上述情况下,我期望类型为[number, string]
2个回答

4

使用映射类型处理元组 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');

是的,它是。请参见Pick类型 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html - Nail Achmedzhanov
谢谢,我已经改成了Pick,但它仍然是一个对象元组。 - undefined
类型 DataFieldType<S,T> = T 扩展 keyof State?Pick<S,T>:never;类型 MappedDataTuple<S,T 扩展 (keyof S)[]> = { [K 在 keyof T]中:DataFieldType<S,T[K]>; } - undefined
实际上我只需要这个:pick<K extends keyof S>(...keys: K[]): Pick<S, K> - undefined
因此,使用Pick作为返回类型,您不需要DataFieldType和MappedDataTuple。 - Nail Achmedzhanov
显示剩余2条评论

1

最简单的方法是:

function getKeysValues(...keys: Array<keyof typeof data>): Array<typeof data[keyof typeof data]> {
    return keys.map(k => data[k]);
}

您也可以添加泛型:

function getKeysValues<K extends keyof typeof data>(...keys: Array<K>): Array<typeof data[K]> {
    return keys.map(k => data[k]);
}

但为了方便,在上述任何情况下,我都会给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]>;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接