gpt4 book ai didi

Typescript 通过鉴别器属性将已鉴别联合类型的数组分组到记录中

转载 作者:行者123 更新时间:2023-12-05 01:52:22 25 4
gpt4 key购买 nike

我正在尝试编写通用“groupBy”函数的 typescript 签名,该函数会将已区分类型的联合数组“传播”到记录中,其中记录的每个字段都是一个可能的鉴别器值并指向一个对象数组来自联合的具体类型。

例子:

interface Dog {
type: 'dog'
dogMetadata: {}
}

interface Cat {
type: 'cat'
catMetadata: {}
}

type Animal = Dog | Cat

const animals: Animal[] = [{ type: 'dog', dogMetadata: {} }, { type: 'cat', catMetadata: {} }]

每个接口(interface)都有一个共同的鉴别器属性,没有其他共同的属性。

这是一个简单的“groupBy”签名,它不传播类型联合值,迫使我向下转换记录的值:

function groupBy<T, K extends string>(arr: T[], keyExtractor: (element: T) => K): Record<K, T[]>

const animalsByType: Record<'dog' | 'cat', Animal[]> = groupBy(animals, it => it.type)
const dogs: Dog[] = animalsByType['dog'] as Dog[] // Must downcast Animal[] to Dog[]

我怎样才能创建一个“groupBy”来识别被区分的联合类型的具体类型?我想要这样的东西:

const animalsByType: { dog: Dog[], cat: Cat[] } = groupBy(animals, it => it.type)
const dogs: Dog[] = animalsByType['dog'] // animalsByType.dog is known to be Dog[] by typescript

实现很简单,Typescript 部分有问题 :) 我正在寻找一个不做假设的通用解决方案,例如鉴别器属性的名称或类型联合中的类型数量。

跟进问题

当联合嵌套在另一个类中时,是否可以使相同的签名起作用?

interface Holder<T> {
data: T
}

const animalHolders: Holder<Animal>[] = animals.map(data => ({ data }))

const dogHolders: Holder<Dog> = groupBy(animalHolders, it => it.data.type) // Any way of doing this?

Playground link

感谢您的帮助。

最佳答案

好问题...

让我们首先创建一些实用程序类型:

type KeysOfType<O, T> = {
[K in keyof O]: O[K] extends T ? K : never;
}[keyof O];

这会提取 O 的所有键指向 T 类型的值.这将用于将判别式的类型限制为属于 string 的类型。类型。它们将在您的输出类型中用作键,因此我们对允许其他类型的判别式并不真正感兴趣。

我们还要添加 Expand<T> 使我们的结果类型在智能感知中看起来更好。

type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;

现在,让我们创建一个类型来表示您的 groupBy 的返回类型功能:

type Return<T, K extends KeysOfType<T, string>> = 
{ [KK in string & T[K]]: { [_ in K]: KK } & T }

或者,可选地,自由地应用 Expand<T>为消费者输入更好的智能感知:

type Return<T, K extends KeysOfType<T, string>> = 
Expand<{ [KK in string & T[K]]: Expand<{ [_ in K]: KK } & T> }>

现在我们可以声明函数了:

function groupBy<T, K extends KeysOfType<T, string>>(
arr: T[],
keyExtractor: (element: T) => T[K]): Return<T, K>{
throw Error();
}

并调用它:

const groups = groupBy(animals, e => e.type)

为了完全类型安全,无论选择哪个鉴别器属性。

Playground Link

关于Typescript 通过鉴别器属性将已鉴别联合类型的数组分组到记录中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71602319/

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