如何在 TypeScript 中合并两个枚举 [英] How to merge two enums in TypeScript

查看:64
本文介绍了如何在 TypeScript 中合并两个枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在 Typescript 中有两个枚举,那么我该如何合并它们

Suppose I have two enums as described below in Typescript, then How do I merge them

enum Mammals {
    Humans,
    Bats,
    Dolphins
}

enum Reptiles {
    Snakes,
    Alligators,
    Lizards
}

export default Mammals & Reptiles // For Illustration purpose, Consider both the Enums have been merged.

现在,当我在另一个文件中importexported value 时,我应该能够访问两个枚举中的值.

Now, when I import the exported value in another file, I should be able to access values from both the enums.

import animalTypes from "./animalTypes"

animalTypes.Humans //valid

animalTypes.Snakes // valid

如何在 TypeScript 中实现这样的功能?

How can I achieve such functionality in TypeScript?

推荐答案

合并问题:

  • 相同的值 => 值被覆盖
  • 相同的键 => 键被覆盖

    Problems with the merge:

    • same values => values are overwritten
    • same keys => keys are overwritten

      ❌ 具有相同值的枚举(=> 值被覆盖)

      ❌ Enums with same values (=> values are overwritten)

      enum AA1 {
        aKey, // = 0
        bKey // = 1
      }
      enum BB1 {
        cKey, // = 0
        dKey // = 1
      }
      

      • ❌ 具有相同键的枚举(=> 键被覆盖)
      • enum AA2 {
          aKey = 1
        }
        enum BB2 {
          aKey = 2
        }
        

        • ✅好
        • enum AA3 {
            aKey, // = 0
            bKey // = 1
          }
          enum BB3 {
            cKey = 2,
            dKey // = 3
          }
          

          • ✅也不错
          • enum AA4 {
              aKey = 'Hello',
              bKey = 0,
              cKey // = 1
            }
            enum BB4 {
              dKey = 2,
              eKey = 'Hello',
              fKey = 'World'
            }
            

            注意:aKey = 'Hello'eKey = 'Hello' 工作,因为带有字符串值的枚举没有这个值作为键

            Note: aKey = 'Hello' and eKey = 'Hello' work because the enum with a string value doesn't has this value as key

            // For aKey = 'Hello', key is working
            type aa4aKey = AA4.aKey; // = AA4.aKey
            // value is not.
            type aa4aValue = AA4.Hello; // ❌ Namespace 'AA4' has no exported member 'Hello'
            type aa4aValue2 = AA4['Hello']; // ❌ Property 'Hello' does not exist on type 'AA4'
            
            console.log(AA4); // { 0: 'bKey', 1: 'cKey', aKey: 'Hello', bKey: 0, cKey: 1 }
            console.log(BB4); // { 2: 'dKey', dKey: 2, eKey: 'Hello', fKey: 'World' }
            

            合并

            • ❌ 使用联合类型
            • type AABB1 = AA4 | BB4; // = AA4 | BB4
              type AABB1key = AABB1['aKey']; // = never
              type AABB1key2 = AABB1.aKey; // ❌ 'AABB1' only refers to a type, but is being used as a namespace here. ts(2702)
              

              • ❌ 使用交叉点类型
              • type AABB1 = AA4 & BB4; // = never
                type AABB1key = AABB1['aKey']; // = never
                

                • ✅ 使用 typeof 的交集类型
                • type AABB2 = (typeof AA4) & (typeof BB4); // = typeof AA4 & typeof BB4
                  type AABB2key = AABB2['aKey']; // = AA4.aKey
                  

                  • ✅ 使用 js 复制
                  • const aabb1 = { ...AA4, ...BB4 };
                    const aabb2 = Object.assign({}, AA4, BB4); // also work
                    // aabb1 = {
                    // 0: 'bKey',
                    // 1: 'cKey',
                    // 2: 'dKey',
                    // aKey: 'Hello',
                    // bKey: 0,
                    // cKey: 1,
                    // dKey: 2,
                    // eKey: 'Hello',
                    // fKey: 'World' }
                    

                    • ✅ 使用 typeof 和 js 副本
                    • const aabb = { ...AA4, ...BB4 };
                      type TypeofAABB = typeof aabb;
                      // type TypeofAABB = {
                      // [x: number]: string;
                      // dKey: BB4.dKey;
                      // eKey: BB4.eKey;
                      // fKey: BB4.fKey;
                      // aKey: AA4.aKey;
                      // bKey: AA4.bKey;
                      // cKey: AA4.cKey;
                      // };
                      

                      提示:您可以对类型和值使用相同的名称

                      Tip: you can use the same name for a type and a value

                      const merged = { ...AA4, ...BB4 };
                      type merged = typeof merged;
                      
                      const aValue = merged.aKey;
                      type aType = merged['aKey'];
                      

                      你的情况

                      如果你想合并你的 2 个枚举,你有 ~3 个选择:

                      Your case

                      If you want to merge your 2 enums you have ~3 choices:

                      enum Mammals {
                        Humans = 'Humans',
                        Bats = 'Bats',
                        Dolphins = 'Dolphins'
                      }
                      
                      enum Reptiles {
                        Snakes = 'Snakes',
                        Alligators = 'Alligators',
                        Lizards = 'Lizards'
                      }
                      
                      export const Animals = { ...Mammals, ...Reptiles };
                      export type Animals = typeof Animals;
                      

                      2.使用唯一编号

                      enum Mammals {
                        Humans = 0,
                        Bats,
                        Dolphins
                      }
                      
                      enum Reptiles {
                        Snakes = 2,
                        Alligators,
                        Lizards
                      }
                      
                      export const Animals = { ...Mammals, ...Reptiles };
                      export type Animals = typeof Animals;
                      

                      3.使用嵌套枚举

                      enum Mammals {
                        Humans,
                        Bats,
                        Dolphins
                      }
                      
                      enum Reptiles {
                        Snakes,
                        Alligators,
                        Lizards
                      }
                      
                      export const Animals = { Mammals, Reptiles };
                      export type Animals = typeof Animals;
                      
                      const bats = Animals.Mammals.Bats; // = 1
                      const alligators = Animals.Reptiles.Alligators; // = 1
                      

                      注意:您还可以使用以下代码合并嵌套的枚举.如果这样做,请注意不要有重复的值!

                      Note: you can also merge the nested enums with the following code. Take care to NOT have duplicated values if you do that!

                      type Animal = {
                        [K in keyof Animals]: {
                          [K2 in keyof Animals[K]]: Animals[K][K2]
                        }[keyof Animals[K]]
                      }[keyof Animals];
                      
                      const animal: Animal = 0 as any;
                      
                      switch (animal) {
                        case Animals.Mammals.Bats:
                        case Animals.Mammals.Dolphins:
                        case Animals.Mammals.Humans:
                        case Animals.Reptiles.Alligators:
                        case Animals.Reptiles.Lizards:
                        case Animals.Reptiles.Snakes:
                          break;
                        default: {
                          const invalid: never = animal; // no error
                        }
                      }
                      

                      这篇关于如何在 TypeScript 中合并两个枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆