假设我有两个枚举,如下面的Typescript中所述,那么我如何合并它们
enum Mammals {
Humans,
Bats,
Dolphins
}
enum Reptiles {
Snakes,
Alligators,
Lizards
}
export default Mammals & Reptiles // For Illustration purpose, Consider both the Enums have been merged.
现在,当我import
另一个文件中的exported value
时,我应该可以从两个枚举中访问值。
import animalTypes from "./animalTypes"
animalTypes.Humans //valid
animalTypes.Snakes // valid
如何在Typescript中实现此类功能?
答案 0 :(得分:9)
我不会提出合并到枚举的解决方案(找不到合适的方法)
但是,如果您希望以某种方式像枚举一样使用它,则仍可以在javascript中使用合并对象。
enum Mammals {
Humans = 'Humans',
Bats = 'Bats',
Dolphins = 'Dolphins',
}
enum Reptiles {
Snakes = 'Snakes',
Alligators = 'Alligators',
Lizards = 'Lizards',
}
const Animals = {
...Mammals,
...Reptiles,
}
然后您可以使用Animals.Snakes或Animals.Dolphins,并且两者均应正确键入并用作枚举
答案 1 :(得分:4)
这里令人困惑的是类型与值。
let
,const
等),它将具有一个值以及一些计算出但未单独命名的类型。type
或interface
,它将创建一个命名类型,但是不会以任何方式在最终JS中输出或考虑。仅在编写应用程序时有用。enum
,它将创建一个静态类型名称,您可以使用 plus 一个输出到JS的实际对象来使用。摘自TS手册:
使用枚举很简单:只需从枚举本身访问任何成员作为属性,然后使用枚举的名称声明类型。
因此,如果您Object.assign()
有两个枚举,它将创建一个新的合并的 value (对象),但不会创建一个新的命名类型。
由于它不再是enum
了,您失去了拥有值和命名类型的优势,但是仍然可以创建单独的类型名称作为解决方法。
幸运的是,值和类型可以使用相同的名称,并且如果导出它们,TS会同时导入两者。
// This creates a merged enum, but not a type
const Animals = Object.assign({}, Mammals, Reptiles);
// Workaround: create a named type (typeof Animals won't work here!)
type Animals = Mammals | Reptiles;
答案 2 :(得分:3)
TypeScript枚举不仅包含您定义的键,还包含数字反转,例如:
Mammals.Humans === 0 && Mammals[0] === 'Humans'
现在,如果您尝试合并它们 - 例如与Object#assign
合并 - 您最终会得到两个具有相同数值的键:
const AnimalTypes = Object.assign({}, Mammals, Reptiles);
console.log(AnimalTypes.Humans === AnimalTypes.Snakes) // true
我认为这不是你想要的。
防止这种情况的一种方法是手动将值分配给枚举并确保它们不同:
enum Mammals {
Humans = 0,
Bats = 1,
Dolphins = 2
}
enum Reptiles {
Snakes = 3,
Alligators = 4,
Lizards = 5
}
或不太明确但等同于:
enum Mammals {
Humans,
Bats,
Dolphins
}
enum Reptiles {
Snakes = 3,
Alligators,
Lizards
}
无论如何,只要您确保合并的枚举具有不同的键/值集,就可以将它们与Object#assign
合并。
<强> Playground Demo 强>
答案 3 :(得分:3)
我想说的做到这一点的正确方法是定义一个新类型:
enum Mammals {
Humans = 'Humans',
Bats = 'Bats',
Dolphins = 'Dolphins',
}
enum Reptiles {
Snakes = 'Snakes',
Alligators = 'Alligators',
Lizards = 'Lizards',
}
type Animals = Mammals | Reptiles;
答案 4 :(得分:0)
相同键=>键被覆盖
❌具有相同值的枚举(=>值被覆盖)
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'
之所以起作用,是因为带有字符串值的枚举没有将此值作为键
// 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
type AABB2 = (typeof AA4) & (typeof BB4); // = typeof AA4 & typeof BB4
type AABB2key = AABB2['aKey']; // = AA4.aKey
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' }
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;
// };
提示:您可以为类型和值使用相同的名称
const merged = { ...AA4, ...BB4 };
type merged = typeof merged;
const aValue = merged.aKey;
type aType = merged['aKey'];
如果要合并2个枚举,则有〜3个选择:
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;
enum Mammals {
Humans = 0,
Bats,
Dolphins
}
enum Reptiles {
Snakes = 2,
Alligators,
Lizards
}
export const Animals = { ...Mammals, ...Reptiles };
export type Animals = typeof Animals;
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
答案 5 :(得分:0)
一个非常简单的解决方案,copied from here
对于两组不同的枚举:
enum WeatherType {
CLOUDY,
SUNNY,
RAIN
}
enum WeatherType {
CLOUDY = 0,
SUNNY = 1,
RAIN = 2
}
然后您可以使用:
type MyMergedEnum = AnEnum & AnotherEnum;
答案 6 :(得分:0)
标记(可能更好)的方法:
export enum Fruit {
COCONUT = "COCO",
BANANA = "BANANA",
}
export enum Vegetable {
BROCCOLI = "BROCCOLI",
}
export const Foods = {
...Fruit,
...Vegetable,
};
export type Food = keyof typeof Foods;
确保您定义枚举的字符串不会发生冲突。 Food
是类型,Foods
是定义枚举的底层映射(通常 js 会为您制作)。这种方式的好处在于:
Foods[Food.BROCCOLI]
是字符串“BROCCOLI”,就像 Fruit[Fruit.COCONUT]
是字符串“COCO”一样,编译器知道这些类型。
因此将 Foods
和 Food
结合起来,您会得到标准的枚举行为。
答案 7 :(得分:-1)
尝试这个枚举示例------
枚举或枚举是TypeScript支持的新数据类型
enum PrintMedia {
Newspaper = 1,
Newsletter,
Magazine,
Book
}
function getMedia(mediaName: string): PrintMedia {
if ( mediaName === 'Forbes' || mediaName === 'Outlook') {
return PrintMedia.Magazine;
}
}
let mediaType: PrintMedia = getMedia('Forbes');