Hoe klasseconstanten implementeren?

In TypeScript kan het sleutelwoord constniet worden gebruikt om klasse-eigenschappen te declareren. Als u dit doet, geeft de compiler een fout met “Een klaslid kan het sleutelwoord ‘const’ niet hebben.”

Ik merk dat ik in de code duidelijk moet aangeven dat een eigenschap niet mag worden gewijzigd. Ik wil dat de IDE of compiler een fout maakt als ik probeer een nieuwe waarde toe te wijzen aan de eigenschap nadat deze is gedeclareerd. Hoe bereiken jullie dit?

Ik gebruik momenteel een alleen-lezen eigenschap, maar ik ben nieuw in Typescript (en JavaScript) en vraag me af of er een betere manier is:

get MY_CONSTANT():number {return 10};

Ik gebruik typoscript 1.8. Suggesties?

PS: ik gebruik nu typescript 2.0.3, dus ik heb Davids antwoord

geaccepteerd


Antwoord 1, autoriteit 100%

TypeScript 2.0 heeft de readonly-modifier:

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

Het is niet echt een constante omdat het toewijzing in de constructor mogelijk maakt, maar dat is hoogstwaarschijnlijk niet erg.

Alternatieve oplossing

Een alternatief is om het trefwoord staticte gebruiken met 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

Dit heeft het voordeel dat het niet toewijsbaar is in de constructor en slechts op één plaats bestaat.


Antwoord 2, autoriteit 10%

Constanten kunnen buiten klassen worden gedeclareerd en binnen je klas worden gebruikt. Anders is de eigenschap geteen goede oplossing

const MY_CONSTANT: string = "wazzup";
export class MyClass {
    public myFunction() {
        alert(MY_CONSTANT);
    }
}

Antwoord 3, autoriteit 8%

U kunt eigenschappen markeren met de modifier readonlyin uw declaratie:

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

@see TypeScript Deep Dive-boek – Alleen-lezen


Antwoord 4, autoriteit 2%

Angular 2 Biedt een erg leuke functie, de zogenaamde Opaque Constants.
Maak een klas & Definieer alle constanten daar met behulp van ondoorzichtige constanten.

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

Injecteer het in providers in
app.module.ts

U kunt het voor alle componenten gebruiken.

BEWERKEN voor Angular 4:

Voor Angular 4 is het nieuwe concept Injection Token & Ondoorzichtige token is verouderd in Angular 4.

Injection Token Voegt functionaliteiten toe aan ondoorzichtige tokens, maakt het mogelijk om type-informatie aan het token toe te voegen via generieke TypeScript, plus injectietokens, waardoor het niet meer nodig is om @Inject toe te voegen

Voorbeeldcode

Angular 2 met ondoorzichtige 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 met injectietokens

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

Injectietokens zijn logisch ontworpen bovenop ondoorzichtige tokens & Ondoorzichtige tokens zijn verouderd in Angular 4.


Antwoord 5

Alle antwoorden met readonlyzijn alleen geschikt als dit een pure TS-omgeving is – als er ooit een bibliotheek van wordt gemaakt, belet dit eigenlijk niets, het geeft alleen waarschuwingen voor de TS-compiler zelf.

Statisch is ook niet correct – dat is het toevoegen van een methode aan de klasse, niet aan een instantievan de klasse – dus je moet het rechtstreeks adresseren.

Er zijn verschillende manieren om dit te beheren, maar de pure TS-manier is om een ​​getterte gebruiken – precies zoals je al hebt gedaan.

De alternatieve manier is om het in te voeren als readonly, maar dan Object.definePropertyte gebruiken om het te vergrendelen – dit is bijna hetzelfde als wat wordt gedaan via de getter, maar je kunt het vergrendelen om een ​​waarde te hebben, in plaats van een methode om het te krijgen –

class MyClass {
    MY_CONSTANT = 10;
    constructor() {
        Object.defineProperty(this, "MY_CONSTANT", {value: this.MY_CONSTANT});
    }
}

De standaardinstellingen maken het alleen-lezen, maar bekijk de docsvoor meer details.


Antwoord 6

Gebruik de readOnly-modifier met de constante die men moet declareren, of men kan een constante buiten de klasse declareren en deze specifiek alleen in de vereiste klasse gebruiken met de get-operator.


Antwoord 7

Hiervoor kunt u de modifier readonlygebruiken. Objecteigenschappen die readonlyzijn, kunnen alleen worden toegewezen tijdens de initialisatie van het object.

Voorbeeld in lessen:

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.

Voorbeeld in letterlijke objecten:

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

Het is ook de moeite waard om te weten dat de modifier readonlypuur een typoscript-constructie is en dat wanneer de TS wordt gecompileerd naar JS, de constructie niet aanwezig zal zijn in de gecompileerde JS. Wanneer we eigenschappen wijzigen die alleen-lezen zijn, zal de TS-compiler ons hierover waarschuwen (het is geldige JS).


Antwoord 8

Voor mij werkt geen van de eerdere antwoorden. Ik moest mijn statische klasse converteren naar enum.
Zoals dit:

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

Vervolgens voeg ik in mijn component een nieuwe eigenschap toe zoals gesuggereerd in andere antwoorden

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

Dan gebruik ik het in de sjabloon van mijn component op deze manier

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

BEWERKEN: Sorry. Mijn probleem was anders dan dat van OP. Ik laat dit hier nog steeds als iemand anders hetzelfde probleem heeft dan ik.

Other episodes