public static const in TypeScript
Czy istnieje coś takiego jak publiczne stałe statyczne w maszynopisie? Mam klasę która wygląda jak:
export class Library {
public static BOOK_SHELF_NONE: string = "None";
public static BOOK_SHELF_FULL: string = "Full";
}
W tej klasie mogę zrobić Library.BOOK_SHELF_NONE
i tsc nie narzeka. Ale jeśli próbuję użyć biblioteki klas gdzie indziej i próbuję zrobić to samo, to ona jej nie rozpoznaje.
8 answers
Oto w co wkomponowany jest ten fragment TS (via TS Playground):
define(["require", "exports"], function(require, exports) {
var Library = (function () {
function Library() {
}
Library.BOOK_SHELF_NONE = "None";
Library.BOOK_SHELF_FULL = "Full";
return Library;
})();
exports.Library = Library;
});
Jak widzisz, obie właściwości zdefiniowane jako public static
są po prostu dołączone do wyeksportowanej funkcji (jako jej właściwości); dlatego powinny być dostępne tak długo, jak poprawnie uzyskasz dostęp do samej funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-10 15:22:21
Jeśli chcesz coś, co zachowuje się bardziej jak statyczna wartość stała w nowoczesnych przeglądarkach (w tym, że nie może być zmieniany przez inny kod), możesz dodać tylko get
accessor do klasy Library
(będzie to działać tylko dla przeglądarek ES5+ i NodeJS):
export class Library {
public static get BOOK_SHELF_NONE():string { return "None"; }
public static get BOOK_SHELF_FULL():string { return "Full"; }
}
var x = Library.BOOK_SHELF_NONE;
console.log(x);
Library.BOOK_SHELF_NONE = "Not Full";
x = Library.BOOK_SHELF_NONE;
console.log(x);
Jeśli ją uruchomisz, zobaczysz, jak próba ustawienia właściwości BOOK_SHELF_NONE
na nową wartość nie działa.
2.0
W TypeScript 2.0, możesz użyć readonly
, aby osiągnąć bardzo podobne wyniki:
export class Library {
public static readonly BOOK_SHELF_NONE = "None";
public static readonly BOOK_SHELF_FULL = "Full";
}
Składnia jest nieco prostsze i bardziej oczywiste. Jednak kompilator zapobiega zmianom, a nie czasowi wykonywania (w przeciwieństwie do pierwszego przykładu, gdzie zmiana nie byłaby w ogóle dozwolona, jak pokazano).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-09 21:05:42
Możesz to zrobić używając przestrzeni nazw , w następujący sposób:
export namespace Library {
export const BOOK_SHELF_NONE: string = 'NONE';
}
Następnie możesz zaimportować go z dowolnego miejsca:
import {Library} from './Library';
console.log(Library.BOOK_SHELF_NONE);
Jeśli potrzebujesz klasy, dołącz ją do przestrzeni nazw: export class Book {...}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-21 00:02:42
Tymczasem można to rozwiązać za pomocą dekoratora w połączeniu z Object.freeze
lub Object.defineProperty
, używam tego, jest trochę ładniejszy niż używanie ton getterów. Możesz skopiować / wkleić bezpośrednio TS Playground , aby zobaczyć go w akcji. - Są dwie opcje
Utwórz poszczególne pola "końcowe"
Poniższy dekorator konwertuje zarówno adnotowane statyczne, jak i niestatyczne pola na "getter-only-properties".
Note : If an instance-variable with no wartość początkowa jest adnotowana @final
, wtedy pierwsza przypisana wartość (bez względu na to, kiedy) będzie ostateczną.
// example
class MyClass {
@final
public finalProp: string = "You shall not change me!";
@final
public static FINAL_FIELD: number = 75;
public static NON_FINAL: string = "I am not final."
}
var myInstance: MyClass = new MyClass();
myInstance.finalProp = "Was I changed?";
MyClass.FINAL_FIELD = 123;
MyClass.NON_FINAL = "I was changed.";
console.log(myInstance.finalProp); // => You shall not change me!
console.log(MyClass.FINAL_FIELD); // => 75
console.log(MyClass.NON_FINAL); // => I was changed.
Dekorator: upewnij się, że umieściłeś to w swoim kodzie!
/**
* Turns static and non-static fields into getter-only, and therefor renders them "final".
* To use simply annotate the static or non-static field with: @final
*/
function final(target: any, propertyKey: string) {
const value: any = target[propertyKey];
// if it currently has no value, then wait for the first setter-call
// usually the case with non-static fields
if (!value) {
Object.defineProperty(target, propertyKey, {
set: function (value: any) {
Object.defineProperty(this, propertyKey, {
get: function () {
return value;
},
enumerable: true,
configurable: false
});
},
enumerable: true,
configurable: true
});
} else { // else, set it immediatly
Object.defineProperty(target, propertyKey, {
get: function () {
return value;
},
enumerable: true
});
}
}
Jako alternatywa dla powyższego dekoratora, istnieje również ścisła wersja tego, która nawet spowoduje błąd, gdy ktoś spróbuje przypisać jakąś wartość do pola z ustawionym "use strict";
. (Jest to jednak tylko część statyczna)
/**
* Turns static fields into getter-only, and therefor renders them "final".
* Also throws an error in strict mode if the value is tried to be touched.
* To use simply annotate the static field with: @strictFinal
*/
function strictFinal(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
value: target[propertyKey],
writable: false,
enumerable: true
});
}
Make every static pole "finał"
Możliwe minusy: będzie to działać tylko dla wszystkich statyk tej klasy lub dla żadnej, ale nie może być stosowane do konkretnych statyk.
/**
* Freezes the annotated class, making every static 'final'.
* Usage:
* @StaticsFinal
* class MyClass {
* public static SOME_STATIC: string = "SOME_STATIC";
* //...
* }
*/
function StaticsFinal(target: any) {
Object.freeze(target);
}
// Usage here
@StaticsFinal
class FreezeMe {
public static FROZEN_STATIC: string = "I am frozen";
}
class EditMyStuff {
public static NON_FROZEN_STATIC: string = "I am frozen";
}
// Test here
FreezeMe.FROZEN_STATIC = "I am not frozen.";
EditMyStuff.NON_FROZEN_STATIC = "I am not frozen.";
console.log(FreezeMe.FROZEN_STATIC); // => "I am frozen."
console.log(EditMyStuff.NON_FROZEN_STATIC); // => "I am not frozen."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-16 23:32:37
Thank You WiredPrairie!
Aby nieco rozszerzyć odpowiedź, Oto kompletny przykład definiowania klasy stałych.
// CYConstants.ts
class CYConstants {
public static get NOT_FOUND(): number { return -1; }
public static get EMPTY_STRING(): string { return ""; }
}
export = CYConstants;
Do użycia
// main.ts
import CYConstants = require("./CYConstants");
console.log(CYConstants.NOT_FOUND); // Prints -1
console.log(CYConstants.EMPTY_STRING); // Prints "" (Nothing!)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-25 10:35:37
Poniższe rozwiązanie działa również od TS 1.7.5.
// Constancts.ts
export const kNotFoundInArray = -1;
export const AppConnectionError = new Error("The application was unable to connect!");
export const ReallySafeExtensions = ["exe", "virus", "1337h4x"];
Do użycia:
// Main.ts
import {ReallySafeExtensions, kNotFoundInArray} from "./Constants";
if (ReallySafeExtensions.indexOf("png") === kNotFoundInArray) {
console.log("PNG's are really unsafe!!!");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-27 15:15:48
Po prostu' Eksportuj 'zmienną i' importuj ' w swojej klasie
export var GOOGLE_API_URL = 'https://www.googleapis.com/admin/directory/v1';
// default err string message
export var errStringMsg = 'Something went wrong';
Teraz użyj go jako,
import appConstants = require('../core/AppSettings');
console.log(appConstants.errStringMsg);
console.log(appConstants.GOOGLE_API_URL);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-09 09:46:50
Możesz użyć gettera, aby Twoja własność była tylko do odczytu. Przykład:
export class MyClass {
private _LEVELS = {
level1: "level1",
level2: "level2",
level2: "level2"
};
public get STATUSES() {
return this._LEVELS;
}
}
Używane w innej klasie:
import { MyClass } from "myclasspath";
class AnotherClass {
private myClass = new MyClass();
tryLevel() {
console.log(this.myClass.STATUSES.level1);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-05 17:55:31