In der Zwischenzeit kann dies durch einen Dekorateur in Kombination mit gelöst werden, Object.freezeoder Object.definePropertyich verwende dies, es ist ein bisschen hübscher als die Verwendung von Tonnen von Gettern. Sie können diesen TS-Spielplatz direkt kopieren / einfügen , um ihn in Aktion zu sehen. - Es gibt zwei Möglichkeiten
Machen Sie einzelne Felder "endgültig"
Der folgende Dekorator konvertiert sowohl kommentierte statische als auch nicht statische Felder in "Nur-Getter-Eigenschaften".
Hinweis : Wenn eine Instanzvariable ohne Anfangswert mit Anmerkungen versehen wird @final, ist der erste zugewiesene Wert (egal wann) der letzte.
// 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.
Der Dekorateur: Stellen Sie sicher, dass Sie dies in Ihren Code aufnehmen!
/**
* 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
});
}
}
Als Alternative zum obigen Dekorator würde es auch eine strikte Version davon geben, die sogar einen Fehler auslösen würde, wenn jemand versuchte, dem Feld "use strict";, das gesetzt wurde , einen Wert zuzuweisen . (Dies ist jedoch nur der statische Teil)
/**
* 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
});
}
Machen Sie jedes statische Feld "endgültig"
Möglicher Nachteil: Dies funktioniert nur für ALLE Statiken dieser Klasse oder für keine, kann jedoch nicht auf bestimmte Statiken angewendet werden.
/**
* 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."