API Overview
17 public exports across 5 mental models. Every entry links to the dedicated page with full guarantees, limitations, and examples.
Freeze
In-place freeze — same reference, no clone. Cheapest form of immutability.
freezeShallow
Freezes only top-level properties with native Object.freeze. Nested objects remain mutable.
function freezeShallow<T>(val: T): T extends object ? Readonly<T> : TdeepFreeze
Recursively freezes all nested objects. Handles circular refs, Symbol keys, and TypedArrays safely. Cached builtins survive post-import Object.freeze override (F1 fix: freezePrototypeChain opt-in).
function deepFreeze<T>(val: T, options?: DeepFreezeOptions): T extends object ? DeepReadonly<T> : T
interface DeepFreezeOptions {
freezePrototypeChain?: boolean // default: false
}View
Proxy-based read-only wrapper. No clone. Original remains mutable if retained (V8).
immutableView
Wraps any object in a Proxy. Every mutation attempt throws TypeError. Handles Map, Set, WeakMap, WeakSet, Date, Array mutators. blockToJSON option (V5 fix) prevents JSON.stringify(view) from invoking target's toJSON().
function immutableView<T extends object>(obj: T, options?: ImmutableViewOptions): T
interface ImmutableViewOptions {
blockToJSON?: boolean // default: false
}isImmutableView
Returns true if the value is an immutable proxy created by immutableView. Uses an unforgeable WeakSet check.
function isImmutableView(val: unknown): booleanassertImmutableView
Throws TypeError if the value is not an immutable proxy.
function assertImmutableView<T>(val: T): asserts val is TimmutableMapView
Wraps a Map in a defensive copy + Proxy. All mutator methods (set, delete, clear) throw. Read methods work normally.
function immutableMapView<K, V>(map: Map<K, V>): ReadonlyMap<K, V>immutableSetView
Wraps a Set in a defensive copy + Proxy. All mutator methods (add, delete, clear) throw.
function immutableSetView<T>(set: Set<T>): ReadonlySet<T>Snapshot
Clone + freeze. True data immutability — original is unaffected, reference is severed.
snapshot
Deep-clones the value with structuredClone, then recursively freezes the clone. Plain object prototypes are severed to null (S1 fix). Non-cloneable values throw (S3).
function snapshot<T>(value: T): DeepReadonly<T>lock
Alias for snapshot. Identical behavior. Kept from v2 for readability at call sites.
function lock<T>(value: T): DeepReadonly<T>secureSnapshot
Snapshot with null prototype + getter-only non-configurable descriptors. Plain objects only. Throws on accessor properties (X1 fix) and non-plain nested values.
function secureSnapshot<T extends Record<string, unknown>>(obj: T): DeepReadonly<T>tamperEvident
Stores value in vault closure + computes 64-bit structural hash (djb2+sdbm). Reaches into Map/Set/Date/RegExp internal slots (T2/T3/T4 fix). Hash is NOT cryptographic — detects bugs, not adversarial attacks.
function tamperEvident<T>(val: T): TamperEvidentVault<T>
interface TamperEvidentVault<T> {
readonly get: () => DeepReadonly<T>
readonly verify: () => boolean
readonly assertIntact: () => void
readonly fingerprint: string
}Isolation
Closure isolation + copy-on-read. Reference extraction is impossible.
vault
Seals value in a closure. Each .get() call returns a fresh frozen copy via structuredClone. Caller can mutate the copy; vault state is unchanged. Reference identity is never exposed.
function vault<T>(val: T): Vault<T>
interface Vault<T> {
readonly get: () => DeepReadonly<T>
}Verification
Runtime checks — no mutation, no side effects.
isDeepFrozen
Returns true if the value and all nested values are frozen. Returns false if any accessor descriptor is present (F4/I1 fix — accessor may return mutable object).
function isDeepFrozen<T>(val: T): booleanassertDeepFrozen
Throws TypeError if the value is not deeply frozen.
function assertDeepFrozen<T>(val: T): asserts val is DeepReadonly<T>checkRuntimeIntegrity
Verifies that 17 builtins constancy depends on still match the references captured at module load time. Also checks Object.prototype key-set fingerprint (I2/I5 fix). Returns an IntegrityResult. Call at app startup; cannot detect pre-import poisoning.
function checkRuntimeIntegrity(): IntegrityResult
interface IntegrityResult {
intact: boolean
compromised: string[] // names of altered builtins
}Type Exports
| Type | Description |
|---|---|
DeepReadonly<T> | Recursively marks all properties as readonly. Handles objects, arrays, Maps, Sets. |
ImmutableViewOptions | Options for immutableView — { blockToJSON?: boolean } |
DeepFreezeOptions | Options for deepFreeze — { freezePrototypeChain?: boolean } |
TamperEvidentVault<T> | Return type of tamperEvident — { get, verify, assertIntact, fingerprint } |
Vault<T> | Return type of vault — { get: () => DeepReadonly<T> } |
IntegrityResult | Return type of checkRuntimeIntegrity — { intact, compromised } |
Freezable | Union: object | Function — types that Object.freeze accepts |