Как реализовать кластерные константы в typescript?

В TypeScript ключевое слово const нельзя использовать для объявления свойств класса. Это приводит к ошибке компилятора: "Член класса не может иметь ключевое слово" const "."

Мне нужно четко указать в коде, что свойство не должно быть изменено. Я хочу, чтобы среда IDE или компилятор выдавали ошибку, если я пытаюсь присвоить новое значение свойству после его объявления. Как вы, ребята, добились этого?

В настоящее время я использую свойство только для чтения, но я новичок в Typescript (и JavaScript) и задаюсь вопросом, есть ли лучший способ:

get MY_CONSTANT():number {return 10};

Я использую машинопись 1.8. Предложения?

PS: сейчас я использую машинопись 2.0.3, поэтому я принял ответ Дэвида

Ответ 1

TypeScript 2.0 имеет модификатор readonly:

class MyClass {
    readonly myReadOnlyProperty = 1;

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

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

Это не совсем константа, потому что она позволяет присваивать в конструкторе, но это, скорее всего, не имеет большого значения.

Альтернативное решение

Альтернативой является использование static ключевого слова с 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

Преимущество этого состоит в том, что он не может быть назначен в конструкторе и существует только в одном месте.

Ответ 2

Константы могут быть объявлены вне классов и использоваться в вашем классе. В противном случае свойство get является хорошим обходным способом

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}

Ответ 4

Angular 2 Обеспечивает очень приятную функцию, называемую непрозрачными константами. Создайте класс и определите все константы там, используя непрозрачные константы.

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/"    
};

Внесите его в поставщиков в app.module.ts

Вы сможете использовать его для всех компонентов.

EDIT для Angular 4:

Для Angular 4 новая концепция - токен впрыска, а непрозрачный токен устарел в Angular 4.

Инъекционный токен Добавляет функциональные возможности поверх непрозрачных токенов, он позволяет привязывать информацию о типе к токену с помощью TypeScript generics, а также токенов Injection, устраняет необходимость добавления @Inject

Пример кода

Angular 2 Использование непрозрачных токенов

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 Использование токенов для инъекций

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!
    ]
  }
]

Инекеры для инъекций спроектированы логически поверх непрозрачных жетонов, а непрозрачные жетоны устарели в Angular 4.

Ответ 5

Используйте модификатор readOnly с константой, которую нужно объявить, или можно объявить константу вне класса и использовать ее специально только в требуемом классе, используя оператор get.

Ответ 6

Для этого вы можете использовать модификатор readonly. Свойства объекта, которые доступны только для readonly могут быть назначены только во время инициализации объекта.

Пример в классах:

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.

Пример в литералах объекта:

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

Также стоит знать, что модификатор readonly является чисто машинописной конструкцией, и когда TS скомпилирован в JS, эта конструкция не будет присутствовать в скомпилированном JS. Когда мы изменяем свойства, которые доступны только для чтения, компилятор TS предупредит нас об этом (это действительно JS).