大佬教程收集整理的这篇文章主要介绍了Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
是否可以检查 @H_103_3@myList 中的值是否来自 Enum1
或 Enum2
但不能同时来自两者?@H_801_9@
enum Enum1 {
Foo = '1',}
enum Enum2 {
bar = '1',}
const myList = (Enum1 | Enum2)[] = [
Enum1.Foo,// not wanted - '1' appears in Enum1 and Enum2
]
首先,TypeScript 中的 unions 是包容性而不是排他性。联合A | B
包括 intersection A & B
。换句话说,联合 A | B
接受所有类型为 A
的值和所有类型为 B
的值,包括同时属于 A
和 B
。@H_801_9@
看起来您正在尝试表示独占并集,它专门排除交集。类似的东西@H_801_9@
const myList: ExclusiveUnion<Enum1,Enum2>[] = [ /* ... */ ];
@H_801_51@
不幸的是,您无法写出适用于所有类型 ExclusiveUnion<T,U>
和 T
的完全通用的 U
类型函数。 TypeScript 不直接支持 否定类型(请参阅 microsoft/TypeScript#29317),因此没有专门排除类型的类型运算符 not
。如果 not
存在,你@R_607_8254@:@H_801_9@
// none of this is valid TypeScript,don't try it:
type ExclusiveUnion<T,U> = (T | U) & (not (T & U));
type ExclusiveUnion<T,U> = (T & not U) | (U & not T);
但它没有,所以你不能。@H_801_9@ @H_801_51@
但是:对于 T
和 U
本身是 literal types 的并集(如 "1" | "2" | null | 3 | undefined | false
)的特殊情况,您可以使用 Exclude
utility type 来过滤T | U
的可分配给交集 T & U
的成员:@H_801_9@
// this works only when T | U are unions of literal types
type ExclusiveUnion<T,U> = Exclude<T | U,T & U>
所以,至少在概念上,你可以写一些类似的东西@H_801_9@
type Enum1XorEnum2 = ExclusiveUnion<Enum1,Enum2>
因为 Enum1
和 Enum2
类型都应该类似于文字字符串/数字类型的联合。这在概念上是行得通的,但在实践中却行不通。问题是枚举很奇怪。@H_801_9@
@H_801_51@
TypeScript 中的
Enum 值有一些相当奇怪的行为;请参阅 microsoft/TypeScript#21998 以了解阻止上述工作的问题。@H_801_9@
我真的认为 TypeScript 中的枚举最好被视为完全不透明。 Enum1.Foo
是 "1"
而不是 "SomethingElseEntirely"
的事实对您的程序的工作无关紧要;如果确实重要,那么我建议应该放弃 enum
以支持诸如文字联合之类的东西。@H_801_9@
例如,让我们看看 Enum1
和 Enum2
的以下定义,它们的结构比您的版本多一点,因此我们实际上愿意接受:@H_801_9@
enum Enum1 {
Foo = '1',Baz = '2',}
enum Enum2 {
Bar = '1',Qux = '3'
}
(因此您希望 ExclusiveUnion<Enum1,Enum3>
为 Enum1.baz | Enum2.Qux
)。您可能会对以下定义感到满意,而不是使用 enum
:@H_801_9@
const Enum1 = {
Foo: '1',Baz: '2'
} as const;
type Enum1 = typeof Enum1[keyof typeof Enum1];
const Enum2 = {
Bar: '1',Qux: '3'
} as const;
type Enum2 = typeof Enum2[keyof typeof Enum2];
这行为类似;值 Enum1
和 Enum2
是具有键值映射的对象。而类型 Enum1
和 Enum2
只是相关值类型的联合:@H_801_9@
// type Enum1 = "1" | "2"
// type Enum2 = "1" | "3"
如果您进行了更改,那么您可以使用上面的 ExclusiveUnion
类型,一切都会如您所愿:@H_801_9@
type Enum1XorEnum2 = ExclusiveUnion<Enum1,Enum2>
// type Enum1XorEnum2 = "2" | "3"
const myList: Enum1XorEnum2[] = [
Enum1.Foo,// error
Enum1.baz,// okay
Enum2.bar,// error
Enum2.Qux // okay
]
如果出于某种原因你真的想继续使用 enum
,你将不得不跳过一些烦人的圈子来获得一个可用的类型。你不能只写@H_801_9@
type Nope = ExclusiveUnion<Enum1,Enum2>; // Enum1 | Enum2
因为编译器将 Enum1 & Enum2
视为 never
并且改变主意非常重要:@H_801_9@
type Enum1XorEnum2 = Enum1 | Enum2 extends infer T ? (
T extends String | number ? (
`${T}` extends `${Enum1}` & `${Enum2}` ? never : T
) : never
) : never;
// type Enum1XorEnum2 = Enum1.baz | Enum2.Qux
那有效(只要您的 enum
只是字符串枚举或数字枚举,但不是两者的混合),但是 blecch。它将枚举值转换为字符串文字类型,然后检查 Enum1 | Enum2
的每个成员并过滤掉在 Enum1
和 Enum2
的字符串文字版本中找到的任何成员。>
@H_801_9@
它像以前一样工作:@H_801_9@
const myList: Enum1XorEnum2[] = [
Enum1.Foo,// error
Enum2.Qux // okay
]
@H_801_51@
就这样吧。如果您真的打算采用两个单独的枚举并检查它们的值,则不能将它们视为不透明的,因此我强烈建议您考虑从 enum
切换到文字联合。如您所见,它们更容易处理。@H_801_9@
Playground link to code@H_801_9@
以上是大佬教程为你收集整理的Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中全部内容,希望文章能够帮你解决Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。