description: "Lossless JSON validation, detached snapshots, deep freezing, structural equality, and exhaustive-union helpers for runtime packages."
English | 中文
dsh-util-values gives runtime packages one implementation for lossless JSON values, immutable object graphs, structural JSON equality, and exhaustive closed-union failures. Callers can validate untrusted values, detach a JSON snapshot, freeze a published value, compare JSON-compatible data, or terminate an unreachable branch without importing a capability package. The helpers hold no shared registry, constructor identity, or mutable module state.
Use isJsonValue() for a predicate and snapshotJsonValue() when the caller also needs a detached copy. Both accept only lossless JSON roots: null, booleans, finite numbers other than negative zero, strings, dense intrinsic arrays, and plain or null-prototype records with enumerable string keys. Cycles, sparse arrays, symbol or non-enumerable own properties, functions, and class instances are rejected.
import { isJsonValue, snapshotJsonValue, type JsonValue } from '@deepseek-ai/dsh-util-values'
declare const input: unknown
if (!isJsonValue(input)) throw new TypeError('expected lossless JSON')
const snapshot = snapshotJsonValue(input) as JsonValue
deepFreeze(value) freezes an object graph in place and returns the same value. It walks enumerable string-keyed children and deliberately leaves live AbortSignal objects mutable. deepEqualJson(a, b) compares JSON-compatible arrays and records structurally; callers must validate hostile or unconstrained values before comparison.
Use assertNever(value, context?) in the default branch of a closed discriminated union. A newly added variant then fails TypeScript compilation at every exhaustive switch, while a runtime value that escaped its declared type throws with the optional context label.
JsonValue.deepEqualJson assumes JSON-compatible inputs — it is not a general object comparator and does not define semantics for prototypes, symbols, accessors, cycles, maps, or sets.deepFreeze follows enumerable string-keyed children — it does not turn arbitrary host objects into immutable data, and it intentionally skips live AbortSignal instances.