gpt4 book ai didi

How to implement deep pick in typescript(如何在打字稿中实现深度挑字)

转载 作者:bug小助手 更新时间:2023-10-25 11:34:03 26 4
gpt4 key购买 nike



I would like to implement deep pick in typescript.

我想在打字稿中实施深度挑选。


My example code is:

我的示例代码是:


interface TestBook {
id: string;
name: string;
}
interface TestUser {
id: string;
email: string;
books: TestBook[];
}

I and I would like to use deep pick like:

我和我想使用深挑,如下所示:


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

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

*/

Problem: There is only Pick in standard typescript and there is no library implement this DeepPick.

问题:在标准打字稿中只有Pick,并且没有实现这个DeepPick的库。


How can I do it? Which technic should I use?

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


I tried to find on google and SO.

我试着在谷歌上搜索。


更多回答

Have you tried stackoverflow.com/a/73913130/18244921?

你试过Stackoverflow.com/a/73913130/18244921吗?

@caTS Looks like it's a whole other topic

@猫看起来像是另一个话题

Why not use something like ts-deep-pick?

为什么不用像ts这样的深挑呢?

Because its use unstandar way for array 'books.[].id' but I need to use books.id

因为它对数组‘books.[].id’使用了不标准的方式,但我需要使用books.id

I came up with this mess. If it works for your use case, I can write up an answer.

我想出了这个烂摊子。如果它适合你的用例,我可以写一个答案。

优秀答案推荐

Let's first define some utility types to get the "head" or "tail" of a path:

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


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

type Tail<T extends string> = T extends `${string}.${infer Rest}` ? Rest : never;

Then our DeepPick can take the heads of the paths and then deep pick the tail:

然后我们的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

If it's not an object, we shouldn't do anything to it. Inside the mapped type, I also added a case for arrays.

如果它不是一个物体,我们就不应该对它做任何事情。在映射类型中,我还为数组添加了一个大小写。


Playground

操场



I tried @zenly's version and found I was losing type hints, so I've modified it slightly. Here's a more opinionated version (zenly's handles a wider set of inputs) that persisted typehints better

我尝试了@zenly的版本,发现我丢失了类型提示,所以我对其进行了轻微的修改。这里有一个更固执己见的版本(zenly‘s处理更广泛的输入集),它更好地持久化了类型提示


type Head<T extends string> = T extends `${infer First}.${string}` ? First : T;
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type Tail<T extends string> = T extends `${string}.${infer Rest}` ? Rest : never;

type DeepPick<TObject, TKey extends string> = UnionToIntersection<TObject extends object
? TKey extends `${infer A}.${infer B}`
? {
[P in Head<TKey> & keyof TObject]: DeepPick<TObject[P], Tail<Extract<TKey, `${P}.${string}`>>>;
}
: TKey extends keyof TObject
? Pick<TObject, TKey>
: never
: TObject>;


@zelsny answer is amazing, but it fails with arrays that can be null or undefined (T[] | null | undefined). This is a solution I found:

@zelny的答案很棒,但对于可以为空或未定义的数组(T[]|NULL|未定义),它会失败。这是我找到的一个解决方案:


type DeepPick<T, K extends string> = T extends object
? NonNullable<T> extends readonly unknown[]
? DeepPick<NonNullable<T>[number], K>[] | Exclude<T, NonNullable<T>>
: {
[P in Head<K> & keyof T]: DeepPick<
T[P],
Tail<Extract<K, `${P}.${string}`>>
>
}
: T

Playground

操场


更多回答

Looks like there is a issue for property starting with same "key" (book vs books) tsplay.dev/mppOpm I think that infer is problem

看起来属性有问题,以相同的“key”开头(Book Vs Book)tsplay.dev/mppOpm我认为推断是有问题的

@teteyi3241 I corrected the implementation now

@eteyi 3241我现在更正了实现

Wow, Is it magic ?

哇,这是魔术吗?

Is it possible to have type suggestions like normal Pick?

有没有可能有像Normal Pick这样的类型建议?

@BoomPT Have you tried the answer below?

@BoomPT你尝试过下面的答案吗?

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com