한편이 조합의 장식을 통해 해결 될 수있다 Object.freeze거나 Object.defineProperty, 내가 이것을 사용하고, 그것은 게터의 톤을 사용하는 것보다 작은 비트 예뻐합니다. 이 TS Playground 를 직접 복사 / 붙여 넣기 하여 실제로 볼 수 있습니다. -두 가지 옵션이 있습니다
개별 필드를 "최종"으로 설정
다음 데코레이터는 주석이 달린 정적 필드와 정적이 아닌 필드를 모두 "getter-only-properties"로 변환합니다.
참고 : 초기 값이없는 인스턴스 변수에 주석이 달린 @final경우 처음 할당 된 값 (언제 상관 없음)이 마지막 값이됩니다.
// 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.
데코레이터 : 이것을 코드에 포함 시키십시오!
/**
* 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
});
}
}
위의 데코레이터에 대한 대안으로, 이것의 엄격한 버전도있을 것입니다. 누군가 "use strict";가 설정 되어 필드에 값을 할당하려고 할 때 오류를 던질 수도 있습니다 . (그러나 이것은 정적 부분 일뿐입니다)
/**
* 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
});
}
모든 정적 필드를 "최종"으로 설정
가능한 단점 : 이것은 해당 클래스의 모든 정적에만 적용되거나 전혀 적용되지 않지만 특정 정적에는 적용 할 수 없습니다.
/**
* 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."