[typescript] How to implement class constants?

In TypeScript, the const keyword cannot be used to declare class properties. Doing so causes the compiler to an error with "A class member cannot have the 'const' keyword."

I find myself in need to clearly indicate in code that a property should not be changed. I want the IDE or compiler to error if I attempt to assign a new value to the property once it has been declared. How do you guys achieve this?

I'm currently using a read-only property, but I'm new to Typescript (and JavaScript) and wonder whether there is a better way:

get MY_CONSTANT():number {return 10};

I'm using typescript 1.8. Suggestions?

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

This question is related to typescript class-constants

The answer is


Angular 2 Provides a very nice feature called as Opaque Constants. Create a class & 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 in providers in app.module.ts

You will be able to use it across every components.

EDIT for Angular 4 :

For Angular 4 the new concept is Injection Token & Opaque token is Deprecated in Angular 4.

Injection Token Adds functionalities on top of Opaque Tokens, it allows to attach type info on the token via TypeScript generics, plus Injection tokens, removes the need of adding @Inject

Example Code

Angular 2 Using Opaque Tokens

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 Using Injection Tokens

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 tokens are designed logically on top of Opaque tokens & Opaque tokens are deprecated in Angular 4.


Either use readOnly modifier with the constant one needs to declare or one might declare a constant outside the class and use it specifically only in the required class using get operator.


All of the replies with readonly are only suitable when this is a pure TS environment - if it's ever being made into a library then this doesn't actually prevent anything, it just provides warnings for the TS compiler itself.

Static is also not correct - that's adding a method to the Class, not to an instance of the class - so you need to address it directly.

There are several ways to manage this, but the pure TS way is to use a getter - exactly as you have done already.

The alternative way is to put it in as readonly, but then use Object.defineProperty to lock it - this is almost the same thing that is being done via the getter, but you can lock it to have a value, rather than a method to use to get it -

class MyClass {
    MY_CONSTANT = 10;

    constructor() {
        Object.defineProperty(this, "MY_CONSTANT", {value: this.MY_CONSTANT});
    }
}

The defaults make it read-only, but check out the docs for more details.


You can mark properties with readonly modifier in your declaration:

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

@see TypeScript Deep Dive book - Readonly


For this you can use the readonly modifier. Object properties which are readonly can only be assigned during initialization of the object.

Example in classes:

class Circle {
  readonly radius: number;

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

  get area() {
    return Math.PI * this.radius * 2;
  }
}

const circle = new Circle(12);
circle.radius = 12; // Cannot assign to 'radius' because it is a read-only property.

Example in Object literals:

type Rectangle = {
  readonly height: number;
  readonly width: number;
};

const square: Rectangle = { height: 1, width: 2 };
square.height = 5 // Cannot assign to 'height' because it is a read-only property

It's also worth knowing that the readonly modifier is purely a typescript construct and when the TS is compiled to JS the construct will not be present in the compiled JS. When we are modifying properties which are readonly the TS compiler will warn us about it (it is valid JS).


For me none of earlier answer works. I did need to convert my static class to enum. Like this:

export enum MyConstants {
  MyFirstConstant = 'MyFirstConstant',
  MySecondConstant = 'MySecondConstant'
}

Then in my component I add new property as suggested in other answers

export class MyComponent {
public MY_CONTANTS = MyConstans;
constructor() { }
}

Then in my component's template I use it this way

<div [myDirective]="MY_CONTANTS.MyFirstConstant"> </div>

EDIT: Sorry. My problem was different than OP's. I still leave this here if someelse have same problem than I.


Constants can be declare outside of classes and use within your class. Otherwise the get property is a nice workaround

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}