typescript - Jak implementovat konstanty třídy?
V TypeScriptu nelze použít klíčové slovo const k deklaraci vlastností třídy. Pokud se to zkusí, kompilátor způsobí chybu s hlášením „Člen třídy nemůže mít klíčové slovo 'const'."
Zjistil jsem, že potřebuji jasně v kódu naznačit, že vlastnost by neměla být měněna. Chci, aby IDE nebo kompilátor hlásil chybu, pokud se pokusím přiřadit nové hodnoty vlastnosti poté, co byla deklarována. Jak to u vás dosahujete?
Momentálně používám vlastnost jen pro čtení, ale zajímalo by mě, jestli existuje lepší způsob:
get MY_CONSTANT():number {return 10};
Používám TypeScript 1.8. Máte nějaké návrhy?
PS: Teď používám TypeScript 2.0.3, takže jsem přijal Davidovu odpověď
Odpověď č. 1
TypeScript 2.0 má modifikátor readonly:
class MyClass {
readonly myReadOnlyProperty = 1;
myMethod() {
console.log(this.myReadOnlyProperty);
this.myReadOnlyProperty = 5; // error, readonly
}
}
new MyClass().myReadOnlyProperty = 5; // error, readonly
Není to přesně konstanta, protože umožňuje přiřazení v konstruktoru, ale to pravděpodobně není velký problém.
Alternativní řešení
Alternativou je použití klíčového slova static spolu s 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
To má tu výhodu, že to nelze přiřadit v konstruktoru a existuje to pouze na jednom místě.
Odpověď č. 2
Konstanty mohou být deklarovány mimo třídy a použity ve vaší třídě. Jinak je vlastnost get hezkým řešením.
const MY_CONSTANT: string = "wazzup";
export class MyClass {
public myFunction() {
alert(MY_CONSTANT);
}
}
Odpověď č. 3
Můžete označit vlastnosti pomocí modifikátoru readonly ve vašem deklaraci:
export class MyClass {
public static readonly MY_PUBLIC_CONSTANT = 10;
private static readonly myPrivateConstant = 5;
}
@viz kniha TypeScript Deep Dive - Readonly
Odpověď č. 4
Angular 2 poskytuje velmi pěknou funkci nazývanou Opaque Constants. Vytvořte třídu a definujte všechny konstanty tam pomocí 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/"
};
Injektujte to do poskytovatelů v app.module.ts
Budete jej moci používat napříč všemi komponentami.
ÚPRAVA pro Angular 4 :
Pro Angular 4 je novým konceptem Injection Token a Opaque token je v Angular 4 zastaralý.
Injekční token přidává funkce nad Opaque Tokens, umožňuje připojit informace o typu k tokenu pomocí generik TypeScriptu, navíc Injekční tokeny odstraňují potřebu přidávat @Inject
Ukázkový kód
Angular 2 Používání neprůhledných tokenů
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 Použití injekčních 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!
]
}
]
Injekční tokeny jsou logicky navrženy nad nezřetelnými tokeny a nezřetelné tokeny jsou v Angular 4 zastaralé.
Odpověď č. 5
Všechny odpovědi s readonly jsou vhodné pouze v čistém prostředí TS - pokud by se z toho někdy měla vytvořit knihovna, pak to ve skutečnosti nic nebrání, jen to poskytuje varování pro samotný TS kompilátor.
Statické také není správné - to znamená přidání metody do třídy, ne do instance třídy - takže je třeba se k tomu přímo přistoupit.
Existuje několik způsobů, jak to řešit, ale čistě v TypeScriptu je způsobem použití getteru - přesně tak, jak jste už udělali.
Alternativní způsob je nastavit ho jako readonly, ale pak použít Object.defineProperty k jeho uzamčení - to je téměř to samé, co se děje přes getter, ale můžete ho uzamknout, aby měl hodnotu, spíše než metodu, kterou použijete k jejímu získání -
class MyClass {
MY_CONSTANT = 10;
constructor() {
Object.defineProperty(this, "MY_CONSTANT", {value: this.MY_CONSTANT});
}
}
Výchozí nastavení jej činí pouze pro čtení, ale podívejte se do dokumentace pro více informací.
