Skip to content
On this page

Freezing at compile time


With libraries like Immer, if you want to freeze an object you have to do it at runtime with a nested Object.freeze, which may be very costly for deeply nested objects (the library does it for you but the performance hit is still there).

Instead, with Structura the freezing is done at compile time via Typescript by adding a nested readonly flag to the produced state. So the performance cost of freezing becomes zero.

// freezing this way is unecessary, unless you want to be sure
// that also the initial state is frozen
const state = [1, 2, 3] as Freeze<number[]>

state.push(4) // DOESN'T COMPILE

// newState gets automatically frozen
const newState = produce(state, (draft) => {

newState.push(5) // DOESN'T COMPILE

You also have the freeze utility, which can work at both runtime and compile time:

import { freeze } from "structurajs";

const frozen_at_compile_time = freeze(newState); 

frozen_at_compile_time.push(5) // DOESN'T COMPILE
frozen_at_compile_time.push(5) // it works

const frozen_at_both_run_and_compile_time = freeze(newState, true); 

frozen_at_both_run_and_compile_time.push(5) // DOESN'T COMPILE
frozen_at_compile_time.push(5) // WILL THROW AN EXCEPTION AT RUNTIME

Note that freeze also has a third argument called "deep" which will only take effect if both deep and runtime are true. If active, deep will freeze objecs/sets/maps at any level of nesting.

const state = { sub: { n: 1 } };
const frozen = freeze(state, true, true);
(frozen as any).sub.n++;  // WILL THROW AN EXCEPTION AT RUNTIME


If you want to unfreeze the object, just use the reverse type:

const newStateUnfrozen = newState as UnFreeze<number[]> 

newState.push(5) // it works

Or if you prefer you can use the unfreeze utility:

import { unfreeze } from "structurajs";

unfreeze(newState).push(5); // it works

ATTENTION: unfreeze will throw an exception if the object was frozen at runtime with Object.freeze or the freeze utility