Sınıf sabitlerinde sınıf sabitleri nasıl uygulanır?


429

TypeScript'te, constanahtar kelime sınıf özelliklerini bildirmek için kullanılamaz. Bunu yapmak, derleyicinin "Sınıf üyesi 'const' anahtar sözcüğünü içeremez" hatasıyla sonuçlanır.

Kendimi açıkça bir özellik değiştirilmemesi gerektiğini kodunda belirtmek gerekir bulmak. Bir kez bildirildikten sonra özelliğe yeni bir değer atamaya çalışırsam IDE veya derleyici hata istiyorum. Bunu nasıl başarıyorsunuz?

Şu anda salt okunur bir özellik kullanıyorum, ancak Typescript (ve JavaScript) konusunda yeniyim ve daha iyi bir yol olup olmadığını merak ediyorum:

get MY_CONSTANT():number {return 10};

1.8 yazı tipini kullanıyorum. Öneriler?

PS: Şimdi daktilo 2.0.3 kullanıyorum, bu yüzden David'in cevabını kabul ettim

Yanıtlar:


651

TypeScript 2.0 readonlydeğiştiriciye sahiptir :

class MyClass {
    readonly myReadOnlyProperty = 1;

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

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

Tam olarak sabit değildir, çünkü yapıcıda atamaya izin verir, ancak bu büyük olasılıkla önemli değildir.

Alternatif çözüm

Alternatif olarak, staticanahtar kelimeyi şu şekilde kullanmaktır 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

Bu, kurucuya atanabilir olmama ve sadece tek bir yerde mevcut olma avantajına sahiptir.


31
Sınıftan dışından özelliklerini erişmek için, eklemeniz gerekir exportönce anahtar kelimeyi classyanı sıra public staticdaha önce readonlyanahtar kelime. Buraya bakın: stackoverflow.com/a/22993349
cbros2008

Soru. Bu readOnly özelliğini sınıfın içinde kullanmak için neden sınıf adına ihtiyaç duyduğunuzu bilmiyor muydunuz? 'MyClass.myReadonlyProperty'
Saiyaff Farouk

@SaiyaffFarouk Sorunuzu anlarsam, yanıt, statik özelliklerin sınıfın bir örneğinde değil, sınıfın bir parçası olarak var olmasıdır. Böylece, bunlara bir sınıf örneği içeren bir değişken değil, sınıf adını kullanarak erişirsiniz.
JeffryHouser

1
export(Harici modüller) ve publicanahtar kelime, bu soru / cevap ile ilişkili olmayan, ancak sadece anlaşılırlığı konusuyla ilgili, ben şahsen kelime var olmayan biriyle üyesi kamu olduğunu söylemek son derece kolay bulabilirsiniz. Ben bu nedenle onunla uğraşmayın ve daha fazla gürültü ekler ve gereksiz yazarak. Ayrıca, kamu üyelerini privateveya olarak işaretlenmiş üyelerden daha farklı kılar.protected . Her neyse, sadece benim düşüncem :)
David Sherret

Anonim sınıflar ne olacak? static readonly myReadOnlyPropertySınıf ilan edildiğinde nasıl erişileceğine dair bir fikrin var export default class { ... }mı? Bunu denedim. MyVar, self.myVar, statik, varsayılan ... çalışmıyor ... (EDIT: default.myVar çözüm gibi görünüyor, ancak bir tür hatası alıyorum)
Alcalyn

67

Sabitler sınıfların dışında bildirilebilir ve sınıfınızda kullanılabilir. Aksi takdirde getözellik güzel bir çözüm

const MY_CONSTANT: string = "wazzup";

export class MyClass {

    public myFunction() {

        alert(MY_CONSTANT);
    }
}

6
Teşekkürler; Bu uygulamadan endişeliyim çünkü taşınabilir değil (modelde, sabit aslında sınıfın bir parçası değil) ve daha geniş bir alana bilgi sızdırıyor, ancak gerçek bir sabit olma avantajına sahip, bu yüzden kazandım ' t Alarm zilini yükseltmeden değiştirebilme.
BeetleJuice

1
get
Endişeyi

3
Başına angular.io/docs/ts/latest/guide/style-guide.html lütfen kullanım deve caase yerine büyük harf. Sabitler için büyük harf kullanılması önerilmez.
Vadim Kirilchuk

12
TypeScript styleguide değil, açısal styleguide .. Soru özellikle TypeScript ile ilgili
VeldMuijz

4
@Esko Her dosya bir modül olduğundan daktiloda const dosyası ile sınırlı olduğuna inanıyorum. Dışarıda erişilebilir hale getirmek için, onu beyan etmeniz export constve daha sonra başka bir dosyadan almanız gerekir . Yine de test etmek oldukça kolay olurdu. Sadece constbir dosyada bildirin ve dışa / içe aktarmadan başka bir dosyada kullanmayı veya tarayıcı konsolundan kullanmayı deneyin.
BeetleJuice


11

Açısal 2 Opak Sabitler olarak adlandırılan çok hoş bir özellik sunar. Bir sınıf oluşturun ve opak sabitleri kullanarak tüm sabitleri tanımlayın.

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 içindeki sağlayıcılara enjekte edin

Her bileşende kullanabilirsiniz.

Açısal 4 için DÜZENLE:

Açısal 4 için yeni konsept Enjeksiyon Simgesi ve Opak belirteç Açısal 4'te kaldırılmıştır.

Enjeksiyon Jetonu Opak Jetonların üstüne işlevler ekler, TypeScript jenerikleri ve ayrıca Enjeksiyon jetonları ile jetona tür bilgisi eklemenize izin verir, @Inject ekleme ihtiyacını ortadan kaldırır

Örnek Kod

Açısal 2 Opak Jetonları Kullanma

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

Açısal 4 Enjeksiyon Jetonlarını Kullanma

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

Enjeksiyon belirteçleri, Opak belirteçlerin üstünde mantıksal olarak tasarlanmıştır ve Opak belirteçler Açısal 4'te kullanımdan kaldırılmıştır.


6
artı bir. Açısal 13 yaşında bir genç kadar stabildir. özellikleri yayınlandıktan birkaç ay sonra kullanımdan kaldırılıyor. küçük.
Stavm

1
eksi bir. Bu sorunun Angular ile ilgisi yoktur. Bir TypeScript çözümü istiyor.
Ben Nieting,

4

Ya bir sabitin bildirmesi gereken sabit ile readOnly değiştiricisini kullanın ya da sınıf dışında bir sabit bildirebilir ve bunu get operatörünü kullanarak yalnızca gerekli sınıfta kullanabilirsiniz.


1

Bunun için readonlydeğiştiriciyi kullanabilirsiniz . Nesne özelliklerireadonlyAtanan yalnızca nesnenin başlatılması sırasında atanabilir.

Sınıflarda örnek:

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.

Nesne değişmezlerinde örnek:

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

readonlyDeğiştiricinin yalnızca bir daktilo yapısı olduğu ve TS'nin JS'ye derlendiği zaman, derlenmiş JS'de yapı bulunmayacağını da bilmeye değer . Salt okunur olan özellikleri değiştirdiğimizde TS derleyicisi bizi bu konuda uyarır (geçerli JS'dir).


-2

Benim için önceki cevapların hiçbiri işe yaramıyor. Statik sınıfımı numaralandırmaya dönüştürmem gerekiyordu. Bunun gibi:

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

Sonra bileşenime diğer yanıtlarda önerildiği gibi yeni özellik ekliyorum

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

Sonra bileşenimin şablonunda bu şekilde kullanıyorum

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

EDIT: Üzgünüm. Benim sorunum OP'lerden farklıydı. Bazılarının benden aynı sorunu varsa hala burada bırakıyorum.


Sabitleri kaydetmek için bir numaralandırma kullanmak her dilde iyi bir uygulama değildir.
Sangimed

Şu anda mevcut çözümler için en iyi çözümdür. Enum'un nasıl kullanılmaması gerektiğini biliyorum, ancak Angular ile ikili sabitlere sahip olmanın en temiz yoludur.
Janne Harju
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.