Nel frattempo questo può essere risolto attraverso un decoratore in combinazione con Object.freezeo Object.defineProperty, sto usando questo, è un po 'più bello rispetto all'utilizzo di tonnellate di getter. Puoi copiare / incollare questo TS Playground direttamente per vederlo in azione. - Ci sono due opzioni
Rendi "finali" i singoli campi
Il seguente decoratore converte i campi statici e non statici con annotazioni in "proprietà solo getter".
Nota : se viene annotata una variabile di istanza senza valore iniziale @final, il primo valore assegnato (indipendentemente da quando) sarà quello finale.
// 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.
The Decorator: assicurati di includerlo nel tuo codice!
/**
* 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
});
}
}
In alternativa al decoratore sopra, ci sarebbe anche una versione rigorosa di questo, che potrebbe anche generare un errore quando qualcuno ha cercato di assegnare un valore al campo con "use strict";l'impostazione. (Questa è solo la parte statica però)
/**
* 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
});
}
Rendi "finale" ogni campo statico
Possibile inconveniente: funzionerà solo per TUTTE le statiche di quella classe o per nessuna, ma non può essere applicato a statiche specifiche.
/**
* 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."