在另一个文件中扩展导入的枚举并使用它
Extending an imported enum in another file and using it
我试图在不同的文件中扩展导入的枚举,并在另一个不同的文件中使用扩展的枚举。
一般情况
base.enum.ts
export enum MyEnum {
a = "Foo"
}
extended.enum.ts
import { MyEnum } from './base.enum';
declare module './base.enum' {
export enum MyEnum {
b = "Bar"
}
}
在index.ts
中使用
import { MyEnum } from './base.enum';
import './extended.enum'; // side-effects import (no usage of export)
console.log(MyEnum.a); // prints "Foo" as expected
console.log(MyEnum.b); // prints undefined, instead of the expected "Bar"
(我在支持字符串值枚举的 TypeScript 2.4.2 中执行此操作)
我已经使用了 and this SO questions as reference and read the following TypeScript issue in GitHub,但仍然找不到解决我的问题的方法。
类似于我的用法示例
animals/base/animal-types.enum.ts:
中的基本枚举 AnimalTypes
export enum AnimalTypes { }
animals/base/animal.ts:
中的基本界面Animal
import { AnimalTypes } from './animal-types';
export interface Animal {
type: AnimalTypes;
}
animals/base/index.ts:
export * from './animal-types.enum';
export * from './animal';
animals/animal-types.enum.ts:
中的扩展枚举 AnimalTypes
import { AnimalTypes } from './base/';
declare module './base/animal-types.enum' {
export enum AnimalTypes {
Cat = "cat",
Dog = "dog"/*,
...*/
}
}
混凝土 class 猫在 animals/cat.ts:
import { Animal, AnimalTypes } from './base/';
import './animal-types.enum';
export class Cat implements Animal {
public type: AnimalTypes = AnimalTypes.Cat; // Usage of AnimalTypes with extended value
}
具体class狗在animals/dog.ts:
import { Animal, AnimalTypes } from './base/';
import './animal-types.enum';
export class Dog implements Animal {
public type: AnimalTypes = AnimalTypes.Dog; // Usage of AnimalTypes with extended value
}
animals/index.ts:
export * from './cat';
export * from './dog';
//...
animals/animals-manager.ts 中的最终用法:
import { Animal, AnimalTypes} from './base/';
import { Cat, Dog/*, ...*/ } from '.';
import './animal-types'; // side-effects import (no usage of export)
export class AnimalsManager {
public animals: { [animal: string]: Animal } = {}; // Animal dictionary (I would use AnimalTypes as key type but that isn't supported yet as far as I know).
constructor() {
this.animals[AnimalTypes.Cat] = new Cat();
this.animals[AnimalTypes.Dog] = new Dog();
}
//...
}
当尝试使用 AnimalManager 的 animals[AnimalTypes.Cat]
时,我将获得 animals[AnimalTypes.Dog]
的值,因为 AnimalTypes.Cat
和 AnimalTypes.Dog
return undefined
(这意味着 animals[AnimalTypes.Cat]
被设置 animals[AnimalTypes.Dog]
覆盖)。
那么,目前是否有一种方法可以如上所述在 TypeScript 中扩展导入的枚举,或者我是否必须绕过我的方式来获得支持这种扩展的自定义枚举?谢谢。
TypeScript 只允许扩展 declare module
中的类型信息,不会从这些声明中执行任何代码。事实上,在 declare module
中包含代码通常是不允许的,例如将带有函数体的函数放在那里会出现 An implementation cannot be declared in ambient contexts
错误。
因此您为 MyEnum
枚举类型声明了附加成员,但该成员未在任何地方初始化,因此其值在运行时为 undefined
。要解决这个问题,您可以自己初始化它:
extended.enum.ts
import { MyEnum } from './base.enum';
declare module './base.enum' {
export enum MyEnum {
b = "Bar"
}
}
const myEnumValues = MyEnum as any;
myEnumValues["b"] = "Bar";
您必须先将 MyEnum
转换为 any
,因为不允许直接初始化:
MyEnum["b"] = "Bar";
没有编译错误
error TS2540:Cannot assign to 'b' because it is a constant or a read-only property.
我试图在不同的文件中扩展导入的枚举,并在另一个不同的文件中使用扩展的枚举。
一般情况
base.enum.ts
export enum MyEnum {
a = "Foo"
}
extended.enum.ts
import { MyEnum } from './base.enum';
declare module './base.enum' {
export enum MyEnum {
b = "Bar"
}
}
在index.ts
中使用import { MyEnum } from './base.enum';
import './extended.enum'; // side-effects import (no usage of export)
console.log(MyEnum.a); // prints "Foo" as expected
console.log(MyEnum.b); // prints undefined, instead of the expected "Bar"
(我在支持字符串值枚举的 TypeScript 2.4.2 中执行此操作)
我已经使用了
类似于我的用法示例
animals/base/animal-types.enum.ts:
中的基本枚举 AnimalTypesexport enum AnimalTypes { }
animals/base/animal.ts:
中的基本界面Animalimport { AnimalTypes } from './animal-types';
export interface Animal {
type: AnimalTypes;
}
animals/base/index.ts:
export * from './animal-types.enum';
export * from './animal';
animals/animal-types.enum.ts:
中的扩展枚举 AnimalTypesimport { AnimalTypes } from './base/';
declare module './base/animal-types.enum' {
export enum AnimalTypes {
Cat = "cat",
Dog = "dog"/*,
...*/
}
}
混凝土 class 猫在 animals/cat.ts:
import { Animal, AnimalTypes } from './base/';
import './animal-types.enum';
export class Cat implements Animal {
public type: AnimalTypes = AnimalTypes.Cat; // Usage of AnimalTypes with extended value
}
具体class狗在animals/dog.ts:
import { Animal, AnimalTypes } from './base/';
import './animal-types.enum';
export class Dog implements Animal {
public type: AnimalTypes = AnimalTypes.Dog; // Usage of AnimalTypes with extended value
}
animals/index.ts:
export * from './cat';
export * from './dog';
//...
animals/animals-manager.ts 中的最终用法:
import { Animal, AnimalTypes} from './base/';
import { Cat, Dog/*, ...*/ } from '.';
import './animal-types'; // side-effects import (no usage of export)
export class AnimalsManager {
public animals: { [animal: string]: Animal } = {}; // Animal dictionary (I would use AnimalTypes as key type but that isn't supported yet as far as I know).
constructor() {
this.animals[AnimalTypes.Cat] = new Cat();
this.animals[AnimalTypes.Dog] = new Dog();
}
//...
}
当尝试使用 AnimalManager 的 animals[AnimalTypes.Cat]
时,我将获得 animals[AnimalTypes.Dog]
的值,因为 AnimalTypes.Cat
和 AnimalTypes.Dog
return undefined
(这意味着 animals[AnimalTypes.Cat]
被设置 animals[AnimalTypes.Dog]
覆盖)。
那么,目前是否有一种方法可以如上所述在 TypeScript 中扩展导入的枚举,或者我是否必须绕过我的方式来获得支持这种扩展的自定义枚举?谢谢。
TypeScript 只允许扩展 declare module
中的类型信息,不会从这些声明中执行任何代码。事实上,在 declare module
中包含代码通常是不允许的,例如将带有函数体的函数放在那里会出现 An implementation cannot be declared in ambient contexts
错误。
因此您为 MyEnum
枚举类型声明了附加成员,但该成员未在任何地方初始化,因此其值在运行时为 undefined
。要解决这个问题,您可以自己初始化它:
extended.enum.ts
import { MyEnum } from './base.enum';
declare module './base.enum' {
export enum MyEnum {
b = "Bar"
}
}
const myEnumValues = MyEnum as any;
myEnumValues["b"] = "Bar";
您必须先将 MyEnum
转换为 any
,因为不允许直接初始化:
MyEnum["b"] = "Bar";
没有编译错误
error TS2540:Cannot assign to 'b' because it is a constant or a read-only property.