2

Can you tell if it possible to create enum like this in Typescript?

public enum FooEnum {

    ITEM_A(1), ITEM_B(2), ITEM_C(3);

    private int order;

    private FooEnum (int order) {
        this.order = order;
    }

    public int getOrder() {
        return order;
    }
}

I have enum like this:

export enum FooEnum {
  ITEM_A = 'ITEM_A',
  ITEM_B = 'ITEM_B',
  ITEM_C = 'ITEM_C',
}

which I am using in TypeORM entities

@Column({ type: 'enum', enum: FooEnum })
foo!: FooEnum

I need to assign enum values to numbers to define their priority. Is possible to do that?

I had also idea to create value object with constants like you can see below but I don't know to use this class on entity, to still save Foo.ITEM_A like 'ITEM_A' string

class Foo {
  public static ITEM_A = new Country(1);
  public static ITEM_B = new Country(2);
  public static ITEM_C = new Country(3);

  constructor(order: number) {
    this.order = order;
  }

  readonly order: number;
}
3
  • 1
    What does Java have to do with this? Commented Dec 10, 2020 at 17:19
  • @RobertHarvey because the question pertains to porting Java code to TypeScript. Not all web devs are Java devs. Commented Dec 10, 2020 at 17:30
  • 2
    You can create a class with readonly properties and make their instances readonly. See: Recreating advanced Enum types in Typescript Commented Dec 10, 2020 at 17:42

2 Answers 2

7

This article describes a way to encapsulate static readonly instance variables using TypeScript.

"Recreating advanced Enum types in Typescript"

And here is the complete Gist (with comments):

GitHub Gist / NitzanHen / ts-enums-complete.ts

Here is an example Country "enum" class:

class Country {
  static readonly FRANCE = new Country('FRANCE', 1);
  static readonly GERMANY = new Country('GERMANY', 2);
  static readonly ITALY = new Country('ITALY', 3);
  static readonly SPAIN = new Country('SPAIN', 4);

  static get values(): Country[] {
    return [
      this.FRANCE,
      this.GERMANY,
      this.ITALY,
      this.SPAIN
    ];
  }

  static fromString(name: string): Country {
    const value = (this as any)[name];
    if (value) return value;
    const cls: string = (this as any).prototype.constructor.name;
    throw new RangeError(`Illegal argument: ${name} is not a member of ${cls}`);
  }

  private constructor(
    public readonly name: string,
    public readonly order: number
  ) { }

  public toJSON() {
    return this.name;
  }
}

export default Country;

Usage

const selectedCountry: Country = Country.FRANCE;

console.log(selectedCountry.order);
Sign up to request clarification or add additional context in comments.

3 Comments

thank you, it looks like exactly what I was looking for :) I will go try it
I tried it, value is mapped from DB, but NestJS it serializes as object in json response. I also have implemented toJSON method
@DenisStephanov The toJSON method is not a standard method... just an example getter for the name value. I would look-up how NestJS serializes a class.
0

I have modified Mr. Polywhirl's answer to have Java's values and valueOf methods in a way that can be applied to multiple enums.

function enumValues<T>(): T[] {
    return Object.values(this as T).filter((value) => typeof value !== "function");
};

function enumValueOf<T>(name: string): T {
    const value = (this as T)[name];
    if (value) return value;

    const cls: string = (this as any).prototype.constructor.name;
    throw new RangeError(`Illegal argument: ${name} is not a member of ${cls}`);
};

export class Country {
  static readonly FRANCE = new Country("FRANCE", 1);
  static readonly GERMANY = new Country("GERMANY", 2);
  static readonly ITALY = new Country("ITALY", 3);
  static readonly SPAIN = new Country("SPAIN", 4);

    private constructor(
    public readonly name: string,
    public readonly order: number
  ) {}

  static values = enumValues<Country>;
  static valueOf = enumValueOf<Country>;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.