typescript - Existuje elegantní způsob, jak nastavit vlastnost třídy pouze jednou?
V TypeScriptu, když jste v rámci třídy, existuje elegantní způsob, jak nastavit hodnotu pouze jednou? Jinými slovy, existuje ekvivalent nastavení hodnoty jako readonly poté, co jí byla přiřazena hodnota?
Například:
class FooExample {
public fixedValue: string;
public setFixedValue(value: string): void {
if (!this.fixedValue) {
// this value should be immutable
this.fixedValue = value;
}
}
}
Nehledám getter, protože vlastnost třídy by mohla být změněna přímo v rámci třídy.
Odpověď č. 1
Po přečtení navrhovaných odpovědí a provedení vlastního výzkumu věřím, že jsem našel nej elegantnější řešení. Nejprve definujete hodnotu jako Object a poté freeze() Object po naplnění související vlastnosti.
class FooExample {
public fixedValue = {
value: '';
};
public setFixedValue(value: string): void {
if (!Object.isFrozen(this.fixedValue)) {
this.fixedValue.value = value;
Object.freeze(this.fixedValue);
}
}
}
Odpověď č. 2
K tomu můžete použít „chytrý“ setter. Myšlenka je definovat setter ve třídě, zevnitř ho smazat a definovat pouze pro čtení vlastnost pomocí metody Object.defineProperty volané s deskriptorem, jehož vlastnost writable je nastavena na false.
Část „změněno přímo v samotné třídě“ by mohla být dosažena prostřednictvím další předefinice vlastnosti. Nezapomeňte vlastnost nejprve udělat konfigurovatelnou.
Tady je, jak by celá věc mohla vypadat (nemyslím si, že by existoval elegantnější způsob, jak to udělat) - runtime verze odpovědi není specifická pro TypeScript:
class ReadonlyFields {
set fixed(value) {
Object.defineProperty(this, "fixed", {
value,
writable: false,
configurable: true,
});
}
doSomething() {
Object.defineProperty(this, "fixed", {
value: 24, //exact logic for changing the value is up to you
writable: false
});
}
}
const r = new ReadonlyFields();
r.fixed = 42;
console.log(r.fixed); //42;
r.fixed = 24;
console.log(r.fixed); //42;
r.doSomething();
console.log(r.fixed); //24;Pokud chcete toto také prosazovat z pohledu typového systému, jednoduše nastavte vlastnost na readonly:
class ReadonlyFields {
readonly fixed!: number;
setFixed(value: number) {
Object.defineProperty(this, "fixed", {
value,
writable: false,
configurable: true,
});
}
doSomething() {
Object.defineProperty(this, "fixed", {
value: 24, //exact logic for changing the value is up to you
writable: false,
});
}
}
const r = new ReadonlyFields();
r.setFixed(42); //OK
//@ts-expect-error
r.fixed = 24;
r.doSomething(); //OK
