I've searched around but can't seem to find an answer for this, hopefully you can help.
How can I add an enum to Image
? This is what I would like ideally but I get an error.
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();
}
}
}
If I move State
into the Graphics
module it works but now State
belongs to Graphics
, which is incorrect. It needs to be part of Image
.
Enums or enumerations are a new data type supported in TypeScript. Most object-oriented languages like Java and C# use enums. This is now available in TypeScript too. In simple words, enums allow us to declare a set of named constants i.e. a collection of related values that can be numeric or string values.
Yes, we can define an enumeration inside a class. You can retrieve the values in an enumeration using the values() method.
The they are useless at runtime argument This is a false argument for typescript in general, let alone Enums. and agree, if at runtime some code tries to change the values of one of your enums, that would not throw an error and your app could start behaving unexpectedly ( that is why Object.
Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.
I think the following is an improvement on KoenT's solution:
export class Image
{
constructor ()
{
this.state = Image.State.Idle;
}
state: Image.State;
}
export namespace Image
{
export enum State
{
Idle,
Loading,
Ready,
Error
}
}
The advantage being that you can leverage named imports:
import {Image} from './image';
let img = new Image()
img.state = Image.State.Error
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);
}
}
Usage:
let program = new Program({ title: `some title` });
program.status = Program.Status.New;
or
program.status = program.Status.New;
Added benefit for Angular 2+ users: this can be used in templates
<div *ngIf="program.status === program.Status.New">
Only display if status of the program is New
</div>
I also bumped into this problem recently. This is what I am currently using as a solution:
// 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;
Then in the place where I'm using the class and its enum:
import Image = require("Image");
let state = Image.State.Idle;
let image = new Image();
state = image.state;
This seems to work fine (even though I don't consider it as the expected way to do this kind of thing).
Hopefully there will be a way in TypeScript to do it this way:
class Image
{
enum State
{
Idle,
Loading,
Ready,
Error
}
constructor()
{
this.state = State.Idle;
}
state: State;
}
export = Image;
I think that this stuff with module augmentation is a very hacky and non-intuitive way* of doing things, so consider this:
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;
That is, just declare the enum in the scope of the class that you want to add it to without exporting it, then expose it through a member of the class.
* Which in regards of structuring and organization of code is BAD, even if it technically works.
Update
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;
Then you get typing like:
var someEnum = Graphics.Image.STATE_ERROR;
var image = new Graphics.Image();
var anotherEnum = image.STATE_IDLE;
I think I may have found a solution...whether it's valid TypeScript I don't know but it works and doesn't cause any compile errors. It's a combination of the above answers.
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();
}
}
}
Can anyone spot any potential issues with this that I haven't noticed?
I'm not sure what you intend to do, but I would have expected that you would want an enum
to represent the possible state values, and then a state
member on the image to indicate the current state of the image.
declare module 'Lib' {
export module Graphics {
enum State {
STATE_IDLE,
STATE_LOADING,
STATE_READY,
STATE_ERROR
}
export class Image {
public state: State;
constructor();
}
}
}
It sounds like you want to declare a class that has enum-like members, rather than declare an enum within a class. i.e:
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();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With