程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中?

开发过程中遇到Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中的问题如何解决?下面主要结合日常开发的经验,给出你关于Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中的解决方法建议,希望对你解决Typescript 检查数组值在 enum1 或 enum 2 中,但不能同时在两者中有所启发或帮助;

是否可以检查 @H_103_3@myList 中的值是否来自 Enum1Enum2 但不能同时来自两者?@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@

但是:对于 TU 本身是 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>

因为 Enum1Enum2 类型都应该类似于文字字符串/数字类型的联合。这在概念上是行得通的,但在实践中却行不通。问题是枚举很奇怪。@H_801_9@ @H_801_51@ TypeScript 中的

Enum 值有一些相当奇怪的行为;请参阅 microsoft/TypeScript#21998 以了解阻止上述工作的问题。@H_801_9@

我真的认为 TypeScript 中的枚举最好被视为完全不透明。 Enum1.Foo"1" 而不是 "SomethingElseEntirely" 的事实对您的程序的工作无关紧要;如果确实重要,那么我建议应该放弃 enum 以支持诸如文字联合之类的东西。@H_801_9@

例如,让我们看看 Enum1Enum2 的以下定义,它们的结构比您的版本多一点,因此我们实际上愿意接受:@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];

这行为类似;值 Enum1Enum2 是具有键值映射的对象。而类型 Enum1Enum2 只是相关值类型的联合:@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
]

不错!@H_801_9@ @H_801_51@

如果出于某种原因你真的想继续使用 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 的每个成员并过滤掉在 Enum1Enum2 的字符串文字版本中找到的任何成员。> @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,请注明来意。
标签:enum