从数组中选择类型受限于其键的键

时间:2019-10-09 17:28:07

标签: typescript

我有以下工作代码:

interface Box {
    length: number;
    width: number;
    height: number;
}

const box: Box = {
    length: 2,
    width: 1,
    height: 3
};

type PickWithArray<T, A extends readonly (keyof T)[]> = Pick<T, A[number]>;

const keysArray = ["length", "width"] as const;
type Extracted = PickWithArray<Box, typeof keys2>;

这很好用,但是当我创建keysArray时,我想将数组的值限制为该类型的键,以便可以在IDE中自动完成。我尝试了以下操作:

type PickWithArrayKeys<T> = Array<keyof T>;
const pickedKeys: PickWithArrayKeys<Box> = ["length", "width"];
const keysArray = [...pickedKeys] as const; // Doesn't work, original type is persisted
type Extracted = PickWithArray<Box, typeof keysArray>;

这不起作用,因为typeof keysArray实际上是("length" | "width" | "height")[],所以Extracted最终是:

type Extracted = {
    length: number;
    width: number;
    height: number; <-- want this to be excluded
}

1 个答案:

答案 0 :(得分:0)

我将引入一个辅助函数,将数组中的值约束为Box的键的元素,而不仅产生Array<keyof Box>

const asKeysArray = <T>() => <K extends keyof T>(...k: K[]) => k;
const asBoxKeysArray = asKeysArray<Box>();

第一个asKeysArray()函数采用类型T并产生一个新函数,该函数仅接受T类型的键。如果我们给它Box,我们将得到asBoxKeysArray()。然后可以这样调用此函数:

const keysArray = asBoxKeysArray("length", "width");
// const keysArray: ("length" | "width")[]

您会看到keysArray的类型为Array<"length" | "width">,足以使Extracted成为您想要的类型:

type Extracted = PickWithArray<Box, typeof keysArray>;
/*
type Extracted = {
    length: number;
    width: number;
}
*/

在旁边:您可能想知道为什么没有单个函数function asKeysArray<T, K extends keyof T>(...k: K[]): K[];。也就是说,为什么我要让一个通用函数接受T并返回一个新的通用函数接受K?答案是在TypeScript中目前无法执行partial type parameter inference(请参阅related question),因此,如果我们要指定T但要推断出K,则必须这样做此功能返回功能的东西或其他解决方法。

无论如何,这应该对您有用。希望能有所帮助;祝你好运!

Link to code