Trong khi đó, điều này có thể được giải quyết thông qua một công cụ trang trí kết hợp với Object.freezehoặc Object.defineProperty, tôi đang sử dụng cái này, nó đẹp hơn một chút so với sử dụng hàng tấn getters. Bạn có thể sao chép / dán trực tiếp TS Playground này để xem nó hoạt động. - Có hai lựa chọn
Làm cho các trường riêng lẻ "cuối cùng"
Trình trang trí sau đây chuyển đổi cả hai trường chú thích tĩnh và không tĩnh thành "thuộc tính chỉ getter".
Lưu ý : Nếu một biến đối tượng không có giá trị ban đầu được chú thích @final, thì giá trị được gán đầu tiên (bất kể khi nào) sẽ là giá trị cuối cùng.
// 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.
Trình trang trí: Hãy chắc chắn rằng bạn bao gồm điều này trong mã của bạn!
/**
* 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
});
}
}
Thay thế cho trình trang trí ở trên, cũng sẽ có một phiên bản nghiêm ngặt về điều này, thậm chí sẽ gây ra lỗi khi ai đó cố gắng gán một số giá trị cho trường "use strict";khi được đặt. (Đây chỉ là phần tĩnh)
/**
* 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
});
}
Làm cho mọi trường tĩnh "cuối cùng"
Nhược điểm có thể có: Điều này sẽ chỉ hoạt động cho TẤT CẢ các thống kê của lớp đó hoặc không có gì, nhưng không thể áp dụng cho các thống kê cụ thể.
/**
* 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."