在打字稿中扩展枚举

Posted

技术标签:

【中文标题】在打字稿中扩展枚举【英文标题】:Extending Enum in typescript 【发布时间】:2019-03-22 07:11:08 【问题描述】:

我希望在枚举中重用某些值。 有关如何实现此类功能的任何建议。

enum someEnum 
    a = 'Some String',
    b = 2,
;

enum extendedEnum 
    c = 'string',
    b = someEnum.b


type someEnumType<T extends someEnum> = T extends someEnum.a ? string :
    T extends someEnum.b ? number : never;

type extendedEnumType<T extends extendedEnum> =
    T extends extendedEnum.c ? string:          // Gives Error
    T extends extendedEnum.b ? number : never;  // Gives Error

【问题讨论】:

请注意,如果您向同一个枚举 enum someEnum c = 'string', b = someEnum.b 声明新值,打字稿会将它们合并在一起......但我不建议这样做,因为它会污染原始枚举 不幸的是,作为enum 无法做到这一点,即必须使用type 解决方法之一,根据 TS 项目经理的说法,这不太可能改变。见github.com/microsoft/TypeScript/issues/… 【参考方案1】:

你可以在你的类型中使用联合:

enum abc 
  a = 1,
  b = 2,
  c = 3


enum def 
  d = 4,
  e = 5,
  f = 6


type abcdef = abc | def;

let x: abcdef;

x = abc.a;
x = def.d;

【讨论】:

仅当您使用 enum 作为类型而不是值时才有效。【参考方案2】:

目前,您不能在 TypeScript 中扩展枚举

另一种选择是使用类型:

enum Color1 
  Red = "Red",
  Green = "Green"


enum Color2 
  Yellow = "Yellow",
  Blue = "Blue"

定义一个名为 Colors 的新类型:

type Colors = Color1 | Color2;

然后你可以像下面这样使用它:

public color: Colors;

ngOnInit(): void 
  const Colors =  ...Color2, ...Color1 ;
  this.color = Colors.Red; // Colors.Green or Colors.Yellow or Colors.Blue

Stackblitz Here

【讨论】:

Colors.Red 不起作用。 Colors 不能像枚举一样使用,您会收到错误 ts2693: "'Colors' 仅指一种类型,但在此处用作值。" 合并类型,而不是枚举【参考方案3】:

我刚刚偶然发现了 2018 年的这篇文章,它解释了如何使用基于字符串的枚举来做到这一点。有关原始评论,请参阅 [1]。

这是一个带注释/果味的版本:

enum someEnum 
  Apple = 'Apple',
  Banana = 'Banana'


enum extendedEnum 
  Pear = 'Pear',
  Grape = 'Grape'


// The key seems to be to declare a type AND
// a const with the same name

type AllFruits = someEnum | extendedEnum;
const AllFruits = ...someEnum, ...extendedEnum;

let f: AllFruits = AllFruits.Grape;

原始发帖人(他似乎一直是 TypeScript 的贡献者并且知道他们在说什么)提到,使用这种方法,你不能使用像 AllFruits.Grape 这样的东西作为' type literal',这意味着你不能这样做:

// This error will appear: 
// 'AllFruits' only refers to a type, but is being used as a namespace here.

interface FruitBowl 
    fruit: AllFruits.Grape    

但这可以通过(一些非常丑陋的东西)来解决:

interface FruitBowl 
    fruit: typeof AllFruits.Grape    

我想这是其他人提到的“类型解决方法”之一。

(全部归功于https://github.com/alangpierce) [1]:https://github.com/microsoft/TypeScript/issues/17592#issuecomment-449440944

【讨论】:

以上是关于在打字稿中扩展枚举的主要内容,如果未能解决你的问题,请参考以下文章

避免任何类型在打字稿中获取枚举值

在打字稿中使用枚举作为接口键

打字稿:如何检查一个值是不是是有效的枚举键值? [复制]

如何在打字稿中访问枚举的名称

使用枚举和泛型在打字稿中获取星期几

字符串枚举类似于打字稿中的类型[重复]