类内的枚举(TypeScript定义文件)


78

我到处搜寻,但似乎找不到答案,希望可以为您提供帮助。如何在图像中添加枚举?这是我理想的状态,但出现错误。

declare module 'Lib' {

  export module Graphics {

    export class Image {

      enum State {}

      static STATE_IDLE: State;
      static STATE_LOADING: State;
      static STATE_READY: State;
      static STATE_ERROR: State;

      constructor();

    }

  }

}

如果我将State移到Graphics模块,则可以工作,但是State属于Graphics ...这是不正确的,它必须是Image的一部分。

有任何想法吗?谢谢

Answers:


59

我认为以下是对KoenT解决方案的改进:

export class Image
{
    constructor ()
    {
        this.state = Image.State.Idle;
    }

    state: Image.State;
}

export namespace Image
{
    export enum State
    {
        Idle,
        Loading,
        Ready,
        Error
    }
}

好处是您可以利用命名的导入:

import {Image} from './image';
let img = new Image()
img.state = Image.State.Error

4
正式参考中的“声明合并”中也描述了此技术。要与此技术配合使用export default,可以export从中删除关键字class并在的右括号后面namespace添加一行。export default Image;namespace
zett42

感谢您的回答!我还不知道该宣言是否合并,..哇,那很强大!
Janis Jansen

它不再工作了。错误:不允许使用“命名空间”和“模块”(无命名空间)。检查typescriptlang.org/docs/handbook/...
Shadoweb

@Shadoweb这绝对仍然可以工作...“无命名空间”错误是ts-lint配置(也是一个有争议的配置),不是打字稿错误。参见palantir.github.io/tslint/rules/no-namespacegithub.com/microsoft/TypeScript/issues/30994
NSjonas

无法正常工作,您不能使用类本身内部的枚举,这是多么的负担...
phil123456

39

这是我的解决方案。

program.ts:

enum Status {
    Deleting,
    Editing,
    Existing,
    New
}

export class Program {
    static readonly Status = Status;
    readonly Status = Program.Status;

    title: string;

    status: Status;

    constructor(init?: Partial<Program>) {
        Object.assign(this, init);
    }
}

用法:

let program = new Program({ title: `some title` });

program.status = Program.Status.New;

要么

program.status = program.Status.New;

为Angular 2+用户增加了好处:可在模板中使用

<div *ngIf="program.status === program.Status.New">
  Only display if status of the program is New
</div>

2
好的方法,但是如果我需要声明一个枚举类型的变量怎么办?enumVar: Program.Status;不工作
Dimanoid

1
这应该是可接受的解决方案中,其他的产生棉绒警告(github.com/bradzacher/eslint-plugin-typescript/blob/master/docs/...
graup

除非您删除,否则无法与Angular一起static使用,因为模板无法使用其组件的静态属性。
Hutch Moore

因此readonly Status = Program.Status;就在下面static
MažvydasTadaravičius

38

最近我也遇到了这个问题。这是我目前正在使用的解决方案:

// File: Image.ts

class Image
{
    constructor()
    {
        this.state = Image.State.Idle;
    }

    state: Image.State;
}

module Image
{
    export enum State
    {
        Idle,
        Loading,
        Ready,
        Error
    }
}

export = Image;

然后在我使用类及其枚举的地方:

import Image = require("Image");

let state = Image.State.Idle;
let image = new Image();
state = image.state;

这似乎很好用(即使我不认为这是执行这种操作的预期方式)。

希望TypeScript中有一种方法可以做到这一点:

class Image
{
    enum State
    {
        Idle,
        Loading,
        Ready,
        Error
    }

    constructor()
    {
        this.state = State.Idle;
    }

    state: State;
}

export = Image;

3

我认为带有模块增强功能的这些东西是一种非常笨拙且不直观的方式*,因此请考虑以下几点:

export module Graphics
{
    enum State
    {
        STATE_IDLE,
        STATE_LOADING,
        STATE_READY,
        STATE_ERROR
    }

    export class Image
    {
        constructor() { }
        public static readonly State = State;
    }
}

//...

let imgState = Graphics.Image.State.STATE_ERROR;

也就是说,只需在要添加它的类的范围内声明枚举而不导出它,然后通过该类的成员公开它即可。

*就代码的结构和组织而言,即使在技术上可行,它也是BAD。

更新资料

declare module Lib
{
    enum State
    {
        STATE_IDLE,
        STATE_LOADING,
        STATE_READY,
        STATE_ERROR
    }

    class ImageClass
    {
        constructor();
        public Prop: any;
    }

    export interface Graphics
    {
        Image: typeof State & ImageClass & (new () => typeof State & ImageClass);
    }
}

declare var Graphics: Lib.Graphics;

然后,您将输入如下内容:

var someEnum = Graphics.Image.STATE_ERROR;
var image = new Graphics.Image();
var anotherEnum = image.STATE_IDLE;

我很感激,但是我试图为现有库编写一个声明,这超出了我的控制范围,因此“ Graphics.Image.State.STATE_ERROR”对我不起作用-它必须是“ Graphics.Image.STATE_ERROR”
Lewis Peel

@LewisPeel啊,对不起。我已经更新了答案,这会给您带来任何价值吗?
亚历克斯

2

我想我可能已经找到了解决方案……我不知道它是否是有效的TypeScript,但是它可以工作并且不会引起任何编译错误。这是以上答案的组合。

declare module 'Lib' {

  module Graphics {

    module Image {
      enum State { }
      var STATE_IDLE: State;
      var STATE_LOADING: State;
      var STATE_READY: State;
      var STATE_ERROR: State;
    }

    class Image {
      constructor();
    }

  }

}

有人可以发现我没有注意到的任何潜在问题吗?


我什至可以甚至从枚举中删除值,而不会影响任何内容。
刘易斯·皮尔2015年

现在您可以通过两种方式访问​​它:Image.State.STATE_IDLEImage.STATE_IDLE。有人看着您的定义来弄清楚他们应该使用什么,这有点困难。
David Sherret 2015年

真正。我已经编辑了答案,并从枚举中删除了值……这更有意义。实际上看起来就像threejs在其定义文件中具有的内容。
刘易斯·皮尔2015年

1

我不确定您打算做什么,但是我曾希望您希望一个enum代表可能的状态值,然后一个state图像上的成员表示该图像的当前状态。

declare module 'Lib' {
    export module Graphics {

        enum State {
            STATE_IDLE,
            STATE_LOADING,
            STATE_READY,
            STATE_ERROR
        }

        export class Image {
            public state: State;

            constructor();
        }

    }
}

听起来您想声明一个具有类似于枚举的成员的类,而不是在一个类中声明一个枚举。即:

declare module 'Lib' {

    export module Graphics {

        export class Image {
            static STATE_IDLE: number;
            static STATE_LOADING: number;
            static STATE_READY: number;
            static STATE_ERROR: number;

            constructor();
        }
    }
}

感谢您的答复,史蒂夫。我访问任何状态值的方式是这样的;Lib.Graphics.Image.STATE_READY而不是公共属性-不是我的决定,而是库的方式。有没有一种方法可以对类进行静态枚举?
刘易斯·皮尔2015年

在那种情况下,我认为您只想在Image类中声明类枚举成员(将是number类型,就像枚举在幕后一样)。
Fenton 2015年

我懂了。尽管我有一个只接受空闲,加载,就绪或错误的函数-如果不是其中之一,则不应允许。如果我将它们声明为数字,人们可以发送“ 100”,这是正确的吗?
刘易斯·皮尔2015年

0

您可以使用相同的名称创建模块和类。这也可能有助于重命名您的枚举,这样您不必重复State两次:

declare module 'Lib' {
    export module Graphics {
        export class Image {
            constructor();
        }

        export module Image {
            export enum State {
                Idle,
                Loading,
                Ready,
                Error
            }
        }
    }
}


那种方法行得通,但是这意味着我必须写“ Lib.Graphics.Image.State.STATE_IDLE”而不是“ Lib.Graphics.Image.STATE_IDLE”
Lewis Peel

2
@LewisPeel然后,您要查找的不是类中的枚举,而是类中的静态数字属性。使用史蒂夫(Steve)的答案,但要显式地为每个属性赋予一个值。static STATE_IDLE: number = 0; static STATE_LOADING: number = 1;等等...
David Sherret 2015年

我认为那是我唯一的选择。遗憾的是,因为就像我说的那样,您可以使用100而不是Image.STATE_LOADING,并且编译器不会对其进行标记...但是当代码运行时,它将引发错误。
刘易斯·皮尔2015年

哦,我忘了这是一个定义文件。您不能将值分配给这些成员,但只需确保在相应的javascript文件中进行设置即可(我原本是说成员而不是属性)
David Sherret 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.