How to implement class constants in typescript?

In TypeScript, the const keyword cannot be used to declare class properties. Doing so causes a compiler error, "class members cannot have the 'const' keyword."

I found myself needing to make it clear in my code that I shouldn't change properties. If I try to assign a new value to a property after it has been declared, I hope the IDE or compiler fails. How did you achieve this goal?

I'm currently using read-only properties, but I'm new to Typescript (and JavaScript) and wonder if there's a better way:

get MY_CONSTANT():number {return 10};

I'm using typescript 1.8. Suggestion?

PS: I am using typescript 2.0.3 now, so I accepted David's answer

#1 building

Constants can be declared outside the class and used in the class. Otherwise, get property is a good solution

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}

#2 building

TypeScript 2.0 has readonly modifier :

class MyClass {
    readonly myReadOnlyProperty = 1;

    myMethod() {
        console.log(this.myReadOnlyProperty);
        this.myReadOnlyProperty = 5; // error, readonly
    }
}

new MyClass().myReadOnlyProperty = 5; // error, readonly

It's not a constant because it allows assignment in the constructor, but it's probably not a big problem.

Alternatives

Another way is to use the static keyword with readonly:

class MyClass {
    static readonly myReadOnlyProperty = 1;

    constructor() {
        MyClass.myReadOnlyProperty = 5; // error, readonly
    }

    myMethod() {
        console.log(MyClass.myReadOnlyProperty);
        MyClass.myReadOnlyProperty = 5; // error, readonly
    }
}

MyClass.myReadOnlyProperty = 5; // error, readonly

The advantage of this is that it cannot be assigned in the constructor, it only exists in one place.

#3 building

Angular 2 provides a very good function called the opaque constant. Create a class and define all the constants there using opaque constants.

import { OpaqueToken } from "@angular/core";

export let APP_CONFIG = new OpaqueToken("my.config");

export interface MyAppConfig {
    apiEndpoint: string;
}

export const AppConfig: MyAppConfig = {    
    apiEndpoint: "http://localhost:8080/api/"    
};

Inject it into the provider in app.module.ts

You will be able to use it in each component.

Edit Angular 4:

For Angular 4, the new concept is that the injection token and opaque token are deprecated in Angular 4.

Injection token adds function on opaque token, which allows to attach type information on token through TypeScript generics, plus injection token, without adding @Inject

Sample code

Angular 2 using opaque markers

const API_URL = new OpaqueToken('apiUrl'); //no Type Check


providers: [
  {
    provide: DataService,
    useFactory: (http, apiUrl) => {
      // create data service
    },
    deps: [
      Http,
      new Inject(API_URL) //notice the new Inject
    ]
  }
]

Angular 4 uses injection token

const API_URL = new InjectionToken<string>('apiUrl'); // generic defines return value of injector


providers: [
  {
    provide: DataService,
    useFactory: (http, apiUrl) => {
      // create data service
    },
    deps: [
      Http,
      API_URL // no `new Inject()` needed!
    ]
  }
]

Injection marks are logically designed above opaque marks, which are deprecated in Angular 4.

#4 building

You can mark properties with the readonly modifier in the Declaration:

export class MyClass {
  public static readonly MY_PUBLIC_CONSTANT = 10;
  private static readonly myPrivateConstant = 5;
}

@see TypeScript Deep Dive book - Readonly

#5 building

Either use the readOnly modifier, or you need to declare a constant, or you can declare a constant outside the class and use it only in the required classes that use the get operator.

Tags: angular TypeScript Javascript

Posted on Tue, 03 Mar 2020 23:19:44 -0800 by brian79