将导入的枚举扩展到另一个文件并使用它

时间:2017-10-15 17:39:58

标签: typescript enums module extending

我尝试在不同的文件中扩展导入的枚举,并在另一个不同的文件中使用该扩展的枚举。

一般情况

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中支持字符串值枚举)

我已使用thisthis SO问题作为参考,并阅读以下TypeScript issue in GitHub,但仍无法找到解决问题的方法。

类似于我的用法示例

动物/ base / animal-types.enum.ts中的基础枚举AnimalTypes:

export enum AnimalTypes { }

基础界面动物动物/ base / animal.ts:

import { AnimalTypes } from './animal-types';
export interface Animal {
    type: AnimalTypes;
}

动物/碱/ index.ts:

export * from './animal-types.enum';
export * from './animal';

动物/动物类型中的扩展枚举AnimalTypes.enum.ts:

import { AnimalTypes } from './base/';
declare module './base/animal-types.enum' {
    export enum AnimalTypes {
        Cat = "cat",
        Dog = "dog"/*,
        ...*/
    }
}

具体类Cat in 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
}

具体类动物狗/狗。:

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
}

动物/ index.ts:

export * from './cat';
export * from './dog';
//...

动物/动物的最终用法 - 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.CatAnimalTypes.Dog都会返回undefined (这意味着通过设置animals[AnimalTypes.Cat])来覆盖animals[AnimalTypes.Dog]

那么,目前是否有一种方法可以像上面所描述的那样在TypeScript中扩展导入的枚举,或者我是否需要破解我的方式以获得支持这种扩展的自定义枚举?感谢。

1 个答案:

答案 0 :(得分:0)

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.