gpt4 book ai didi

typescript - 折叠一个有区别的联合——从联合派生出一个包含所有可能的键值组合的伞型

转载 作者:行者123 更新时间:2023-12-04 11:23:14 26 4
gpt4 key购买 nike

我有一个受歧视的工会,例如:

type Union = { a: "foo", b: string, c: number } | {a: "bar", b: boolean }
我需要派生一个包含所有潜在属性的类型,并分配可能在 Union 的任何成员上找到的类型。 ,即使只定义在一些 - 在我的例子中:
type CollapsedUnion = { 
a: "foo" | "bar",
b: string | boolean,
c: number | undefined
}
我怎样才能制作一个派生出这种折叠联合的泛型?
我需要一个支持任何大小联合的泛型。
可以实现类似的行为 as a byproduct by using native Omit utility ,但对我来说不幸的是,它遗漏了每个工会成员都不存在的属性(不将它们计入 undefined 或通过 ? )。

最佳答案

我找到了一个 两个方法)!
编辑:这是一个具有两个单独类型参数的解决方案。有关具有单个联合类型参数的解决方案,请参见下方。

// The source types
type A = { a: "foo", b: string, c: number }
type B = { a: "bar", b: boolean }

// This utility lets T be indexed by any (string) key
type Indexify<T> = T & { [str: string]: undefined; }

// Where the magic happens ✨
type AllFields<T, R> = { [K in keyof (T & R) & string]: Indexify<T | R>[K] }

type Result = AllFields<A, B>
/**
* 🥳
* type Result = {
* a: "foo" | "bar";
* b: string | boolean;
* c: number | undefined;
* }
*/
工作原理 AllFields是映射类型。映射类型的“关键”部分
[K in keyof (T & R) & string]
意味着 K扩展联合的键 T & R ,这意味着它将是 T 中的所有键的联合。或在 R .这是第一步。它确保我们使用所有必需的键创建一个对象。 & string是必要的,因为它指定 K也必须是一个字符串。无论如何,情况几乎总是如此,因为 JS 中的所有对象键都是字符串(偶数)——除了符号,但无论如何这些都是不同的鱼。
类型表达式
Indexify<T | R>
返回联合类型 TR但是添加了字符串索引。这意味着如果我们尝试通过 K 索引它,TS 不会抛出错误。即使 K不存在于 T 之一中或 R .
最后
Indexify<T | R>[K]
意味着我们正在通过 K 索引这个 union-with-undefineds-for-string-indexes .其中,如果 KT 的键, R或两者都将导致该键的值类型。
否则会回退到 [string]: undefined index 并导致值为 undefined。
Here's a playground link

编辑:单个通用参数的解决方案
您指定您实际上并不希望这适用于两个类型参数,而是使用现有的联合类型,无论联合中有多少成员。
付出了鲜血、汗水和泪水,但我已经明白了。
// Magic as far as I'm concerned.
// Taken from https://stackoverflow.com/a/50375286/3229534
type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

// This utility lets T be indexed by any key
type Indexify<T> = T & { [str: string]: undefined; }

// To make a type where all values are undefined, so that in AllUnionKeys<T>
// TS doesn't remove the keys whose values are incompatible, e.g. string & number
type UndefinedVals<T> = { [K in keyof T]: undefined }

// This returns a union of all keys present across all members of the union T
type AllUnionKeys<T> = keyof UnionToIntersection<UndefinedVals<T>>

// Where the (rest of the) magic happens ✨
type AllFields<T> = { [K in AllUnionKeys<T> & string]: Indexify<T>[K] }


// The source types
type A = { a: "foo", b: string, c: number }
type B = { a: "bar", b: boolean; }

type Union = A | B

type Result = AllFields<Union>
/**
* 🥳
* type Result = {
* a: "foo" | "bar";
* b: string | boolean;
* c: number | undefined;
* }
*/
我收到了 UnionToIntersection 来自@jcalz 的精彩回答。我试图理解它,但不能。无论如何,我们可以将其视为将联合类型转换为交集类型的魔术盒。这就是我们获得想要的结果所需要的全部内容。
New TS playground link

关于typescript - 折叠一个有区别的联合——从联合派生出一个包含所有可能的键值组合的伞型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65750673/

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