typescript - 在另一个文件中扩展导入的枚举并使用它

标签 typescript enums module extending

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

一般情况

基础.enum.ts

export enum MyEnum {
    a = "Foo"
}

扩展.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仍然找不到解决我的问题的方法。


类似于我的用法示例

animals/base/animal-types.enum.ts 中的基本枚举 AnimalTypes:

export enum AnimalTypes { }

基础接口(interface)Animal in animals/base/animal.ts:

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"/*,
        ...*/
    }
}

animals/cat.ts 中的具体类 Cat:

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
}

animals/dog.ts 中的具体类 Dog:

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';
//...

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.CatAnimalTypes.Dog 返回 undefined(这意味着 animals[AnimalTypes.Cat] 被设置 animals[AnimalTypes.狗]).


那么,目前是否有一种方法可以如上所述在 TypeScript 中扩展导入的枚举,或者我是否必须绕过我的方式来获得支持这种扩展的自定义枚举?谢谢。

最佳答案

TypeScript 只允许扩展 declare module 中的类型信息,这些声明不会执行任何代码。事实上,里面有代码 declare module通常是不允许的,例如将一个带有函数体的函数放在那里会给出 An implementation cannot be declared in ambient contexts错误。

因此您为 MyEnum 声明了附加成员枚举类型,但该成员未在任何地方初始化,因此其值为 undefined在运行时。要解决这个问题,您可以自己初始化它:

扩展.enum.ts

import { MyEnum } from './base.enum';

declare module './base.enum' {
    export enum MyEnum {
        b = "Bar"
    }
}

const myEnumValues = MyEnum as any;
myEnumValues["b"] = "Bar";

你必须投 MyEnumany首先,因为不允许直接初始化:

MyEnum["b"] = "Bar";

没有编译错误

error TS2540:Cannot assign to 'b' because it is a constant or a read-only property.

关于typescript - 在另一个文件中扩展导入的枚举并使用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46758049/

相关文章:

ruby-on-rails - 遇到 Ruby mixin 模块的规范问题

inheritance - golang 关注点分离与可用性

javascript - ReactJS:将index.js转换为index.tsx - 找不到模块:错误:无法解析 './App'

c - 在 C 中如何使用大小写将枚举转换为字符串?

module - 受子签名约束的 OCaml 子模块

c++ - 在 C++ 0x 中打开枚举类

java - 在Java中,使用Enums的更好方法是什么?使用静态常量还是使用构造函数和文件外常量?

Angular2 错误 : There is no directive with "exportAs" set to "ngForm"

typescript - 在 VS 代码 : [ts] Cannot find module '@src/xxx' 中

angular - 错误 TS2339 : Property 'handleError' does not exist on type 'HeroService' with Angular