Deep equals¶
deepEquals validates that a value is deeply equal to an expected structural value.
It performs deep equality comparison against JSON-compatible values (primitives, arrays, and plain objects). Complex objects like class instances, Maps, Sets, or Dates are rejected. If the value is not structural or doesn't match the expected value, the rule emits a single validation event. Otherwise, it produces no validation output.
Signature¶
Through the API:
.deepEquals(expected: unknown)
And internally:
export const deepEquals = (expected: unknown): ValidationRule
(value: unknown, path: FieldPath) => Promise<ReadonlyArray<JaneEvent>>
Events¶
| Event code | Description |
|---|---|
object.not.plain-object |
Value is not a JSON-compatible structural value |
object.not.deeply-equal |
Value does not match the expected structure |
Design rationale¶
- Provides deep structural equality validation for JSON-compatible data.
- Accepts primitives, arrays, and plain objects.
- Rejects complex object types that aren't JSON-serializable.
- Uses deep equality comparison for nested structures.
- Useful for exact structural matching requirements.
- Never coerces or normalizes — validation is explicit and opt-in.
- Emits exactly one event per failure for clarity and composability.
- Async-compatible and returns a readonly array of
JaneEventobjects.
Invoke¶
deepEquals runs only when explicitly included in a boundary or pipeline. It does not run automatically.
The rule activates when:
- The value is any JavaScript value.
- If the value is not a structural value (primitive, array, or plain object), emits
object.not.plain-object. - If the value is structural but doesn't match the expected value, emits
object.not.deeply-equal. - If the value matches the expected structure → returns an empty result set.
Examples¶
Valid exact match¶
await deepEquals({ name: "John", age: 30 })({ name: "John", age: 30 }, "$");
// → []
Array match¶
await deepEquals([1, 2, 3])([1, 2, 3], "$");
// → []
Primitive match¶
await deepEquals("hello")("hello", "$");
// → []
Value doesn't match¶
await deepEquals({ name: "John" })({ name: "Jane" }, "$");
// → [
// JaneEvent{
// kind: "error",
// code: "object.not.deeply-equal",
// path: "$",
// ...
// }
// ]
Complex object (invalid)¶
await deepEquals({ name: "John" })(new Date(), "$");
// → [
// JaneEvent{
// kind: "error",
// code: "object.not.plain-object",
// path: "$",
// ...
// }
// ]