如何在打字稿中实现深度选择

tet*_*241 4 javascript types object typescript

我想在打字稿中实现深度选择。

我的示例代码是:

interface TestBook {
    id: string;
    name: string;
}
interface TestUser {
    id: string;
    email: string;
    books: TestBook[];
}
Run Code Online (Sandbox Code Playgroud)

我和我想使用深度选择,例如:

const foo: DeepPick<TestUser, 'id' | 'books.name'> = {...
/*

{
  id: ..
  books: [{name: ...}]
}

*/
Run Code Online (Sandbox Code Playgroud)

问题:仅在标准打字稿中存在Pick,并且没有库实现此DeepPick

我该怎么做?我应该使用哪种技术?

我试图在谷歌和SO上找到。

moc*_*cha 9

我们首先定义一些实用程序类型来获取路径的“头”或“尾”:

type Head<T extends string> = T extends `${infer First}.${string}` ? First : T;

type Tail<T extends string> = T extends `${string}.${infer Rest}` ? Rest : never;
Run Code Online (Sandbox Code Playgroud)

然后我们的 DeepPick 可以选取路径的头部,然后深度选取尾部:

type DeepPick<T, K extends string> = T extends object ? {
  [P in Head<K> & keyof T]: T[P] extends readonly unknown[] ? DeepPick<T[P][number], Tail<Extract<K, `${P}.${string}`>>>[] : DeepPick<T[P], Tail<Extract<K, `${P}.${string}`>>>
} : T
Run Code Online (Sandbox Code Playgroud)

如果它不是一个对象,我们就不应该对它做任何事情。在映射类型内部,我还添加了一个数组的情况。

操场