Jak zaimplementować stałe klas w maszynopisie?

429

W TypeScript tego constsłowa kluczowego nie można użyć do zadeklarowania właściwości klasy. Powoduje to błąd kompilatora: „Członek klasy nie może mieć słowa kluczowego„ const ”.

Czuję potrzebę wyraźnego wskazania w kodzie, że właściwość nie powinna być zmieniana. Chcę, aby IDE lub kompilator popełnił błąd, jeśli spróbuję przypisać nową wartość do właściwości po jej zadeklarowaniu. Jak to osiągacie?

Obecnie używam właściwości tylko do odczytu, ale jestem nowy w maszynopisie (i JavaScript) i zastanawiam się, czy istnieje lepszy sposób:

get MY_CONSTANT():number {return 10};

Używam maszynopisu 1.8. Propozycje?

PS: Teraz używam maszynopisu 2.0.3, więc zaakceptowałem odpowiedź Davida

Sok z żuka
źródło

Odpowiedzi:

651

TypeScript 2.0 ma readonlymodyfikator :

class MyClass {
    readonly myReadOnlyProperty = 1;

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

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

Nie jest to dokładnie stała, ponieważ pozwala na przypisanie w konstruktorze, ale najprawdopodobniej nie jest to wielka sprawa.

Alternatywne rozwiązanie

Alternatywą jest użycie staticsłowa kluczowego z 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

Ma to tę zaletę, że nie można go przypisać do konstruktora i istnieje tylko w jednym miejscu.

David Sherret
źródło
31
Aby uzyskać dostęp do właściwości spoza klasy, musisz dodać exportsłowo kluczowe zarówno przed, classjak i public staticprzed readonlysłowem kluczowym. Zobacz tutaj: stackoverflow.com/a/22993349
cbros2008
Pytanie. Czy nie było pojęcia, dlaczego potrzebujesz nazwy klasy, aby użyć tej właściwości readOnly w samej klasie? „MyClass.myReadonlyProperty”
Saiyaff Farouk
@SaiyaffFarouk Jeśli rozumiem twoje pytanie, odpowiedź jest taka, że ​​właściwości statyczne istnieją jako część klasy, a nie na instancji klasy. Dostęp do nich można uzyskać, używając nazwy klasy, a nie zmiennej zawierającej instancję klasy.
JeffryHouser,
1
W export(moduły zewnętrzne) oraz publicsłowa kluczowe są związane z tym pytanie / odpowiedź, ale na temat jednoznaczność, ja osobiście uważam, że bardzo łatwo powiedzieć, że członek jest publiczny, gdy słowo kluczowe nie istnieje. Z tego powodu nie zawracam sobie tym głowy, ponieważ powoduje to większy hałas i nie wymaga pisania. To także odróżnia członków publicznych od tych oznaczonych jako privatelub protected. W każdym razie, tylko moja opinia :)
David Sherret
Co z anonimowymi zajęciami? Jakieś pomysły na to, jak uzyskać dostęp, static readonly myReadOnlyPropertygdy deklarowana jest klasa export default class { ... }? Próbowałem this.myVar, self.myVar, statyczny, domyślny ... nie działa ... (EDYCJA: default.myVar wydaje się być rozwiązaniem, ale dostaję błąd typu)
Alcalyn
67

Stałe mogą być deklarowane poza klasami i używane w twojej klasie. W przeciwnym razie getwłaściwość jest dobrym obejściem

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}
j3ff
źródło
6
Dzięki; Martwię się o tę implementację, ponieważ nie jest przenośna (w modelu stała nie jest tak naprawdę częścią klasy) i przenosi informacje do większego zakresu, ale ma tę zaletę, że jest stałą, więc wygrałem ” być w stanie to zmienić bez podnoszenia dzwonków alarmowych.
Sok z żuka
1
Rozumiem obawy i uważam, że korzystanie z getnieruchomości jest bardzo odpowiednie w twoim przypadku
j3ff
3
W przypadku angular.io/docs/ts/latest/guide/style-guide.html użyj wielbłąda zamiast wielkich liter. Wielkie litery dla stałych nie są zalecane.
Vadim Kirilchuk
12
Kątowy poradnik stylów, nie poradnik stylów TypeScript .. Pytanie dotyczyło konkretnie TypeScript
VeldMuijz
4
@Esko Wierzę, że w maszynopisie const jest ograniczony do pliku, ponieważ każdy plik jest modułem. Aby był dostępny na zewnątrz, musisz go zadeklarować, export consta następnie zaimportować z innego pliku. Byłoby to jednak dość łatwe do przetestowania. Po prostu zadeklaruj plik constw jednym pliku i spróbuj użyć go w innym pliku bez eksportu / importu lub użyj go z konsoli przeglądarki.
BeetleJuice,
11

Angular 2 Zapewnia bardzo miłą funkcję o nazwie Stałe nieprzezroczyste. Utwórz klasę i Zdefiniuj wszystkie stałe za pomocą nieprzezroczystych stałych.

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

Wstrzyknij go dostawcom w app.module.ts

Będziesz mógł używać go we wszystkich komponentach.

EDYCJA dla Angular 4:

W przypadku Angulara 4 nowa koncepcja to Injection Token, a nieprzezroczysty token jest przestarzały w Angular 4.

Token wtrysku Dodaje funkcje na nieprzezroczyste tokeny, pozwala dołączyć informacje o typie do tokena za pomocą ogólnych znaków TypeScript oraz tokenów wtrysku, eliminuje potrzebę dodawania @Inject

Przykładowy kod

Angular 2 Korzystanie z nieprzezroczystych tokenów

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 Korzystanie z żetonów wtryskowych

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

Żetony wtrysku są logicznie zaprojektowane na żetonach nieprzezroczystych, a żetony nieprzezroczyste są nieaktualne w Angular 4.

Parth Ghiya
źródło
6
plus jeden. Angular jest tak samo stabilny jak 13-letni nastolatek. przestają być dostępne w kilka miesięcy po ich wydaniu. drobny.
Stavm,
1
minus jeden. To pytanie nie ma nic wspólnego z Angularem. To wymaga rozwiązania TypeScript.
Ben Nieting
4

Albo użyj modyfikatora readOnly ze stałą, którą należy zadeklarować, albo można zadeklarować stałą poza klasą i używać jej konkretnie tylko w wymaganej klasie za pomocą operatora get.

Krishna Ganeriwal
źródło
1

W tym celu możesz użyć readonlymodyfikatora. Właściwości obiektu, które readonlymożna przypisać tylko podczas inicjalizacji obiektu.

Przykład w klasach:

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.

Przykład w literałach obiektowych:

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

Warto również wiedzieć, że readonlymodyfikator jest wyłącznie konstrukcją maszynopisu, a gdy TS jest kompilowany do JS, konstrukcja nie będzie obecna w skompilowanym JS. Gdy modyfikujemy właściwości, które są tylko do odczytu, kompilator TS ostrzeże nas o tym (jest to poprawny JS).

Willem van der Veen
źródło
-2

Dla mnie żadna z wcześniejszych odpowiedzi nie działa. Musiałem przekonwertować klasę statyczną na wyliczanie. Lubię to:

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

Następnie w moim komponencie dodaję nową właściwość, jak sugerowano w innych odpowiedziach

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

Następnie w szablonie mojego komponentu używam go w ten sposób

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

EDYCJA: Przepraszam. Mój problem był inny niż OP. Nadal zostawiam to tutaj, jeśli niektóre osoby mają ten sam problem niż ja.

Janne Harju
źródło
Używanie wyliczenia do zapisywania stałych nie jest dobrą praktyką w żadnym języku.
Sangimed
To najlepsze rozwiązanie dla obecnie dostępnych rozwiązań. Wiem, że nie należy używać wyliczania, ale w Angular jest to najczystszy sposób na uzyskanie stałych, które można powiązać.
Janne Harju