API Reference

Everything is a named export from the package root:

TypeScript
import {
  diff, patch, diffWith,           // functions
  DELETED, ADDED, CHANGED, INSERTED, REMOVED, // op-type constants
} from "@opentf/obj-diff";
ExportKindSummary
difffunctionDeep-compare two values into a list of operations.
patchfunctionApply a diff to reconstruct the target.
diffWithfunctiondiff with a custom equality function.
DiffResulttypeThe shape of a single operation.
Op constantsconstDELETED, ADDED, CHANGED, INSERTED, REMOVED.

diff

TypeScript
function diff(a: unknown, b: unknown): DiffResult[]

Performs a deep comparison and returns the list of operations that transform a into b. An empty array means the two values are deeply equal.

Parameters

NameTypeDescription
aunknownThe source (original) value.
bunknownThe target value to compare against.

ReturnsDiffResult[], in application order.

TypeScript
diff({ a: 1 }, { a: 2 });
//=> [{ type: 2, path: ["a"], value: 2 }]

Compact array diffs

diff trims the common prefix and suffix of arrays and resolves the remaining middle with a bounded shortest-edit-script (Myers LCS) pass. Inserting one element at the front of a 10,000-element array produces 1 op, not 10,001:

TypeScript
diff([1, 2, 3], [0, 1, 2, 3]);
//=> [{ type: 3, path: [0], value: 0 }]

diff([1, 2, 3, 4], [1, 4]);
//=> [{ type: 4, path: [1] }, { type: 4, path: [1] }]

INSERTED / REMOVED indexes are application-time (RFC 6902 style): apply the ops in order and each index is valid at the moment it is applied. When two arrays are too different (an internal edit-distance cap is exceeded), diff falls back to index-by-index comparison to bound worst-case time and memory.


patch

TypeScript
function patch(obj: unknown, patches: DiffResult[]): unknown

Applies a diff to obj and returns the reconstructed value. The round-trip always holds: patch(a, diff(a, b)) is deep-equal to b.

Parameters

NameTypeDescription
objunknownThe source value to apply the diff to.
patchesDiffResult[]A diff produced by diff or diffWith.

Returns — the patched value.

TypeScript
const a = { a: 1 };
const b = { a: 2 };

patch(a, diff(a, b)); //=> { a: 2 }

Added and changed values are placed into the result by reference, not cloned. See Caveats for aliasing details.


diffWith

TypeScript
function diffWith(
  a: unknown,
  b: unknown,
  isChanged: (a: object, b: object) => boolean | undefined,
): DiffResult[]

Like diff, but you supply a comparator to override equality for specific object types (e.g. MongoDB ObjectId, custom classes).

Parameters

NameTypeDescription
aunknownThe source value.
bunknownThe target value.
isChanged(a, b) => boolean | undefinedReturn true/false to force the result, or undefined to fall back to the built-in comparison. Invoked only when both values are objects.

ReturnsDiffResult[].

TypeScript
import { diffWith } from "@opentf/obj-diff";
import { ObjectId } from "bson";

diffWith(recordA, recordB, (a, b) => {
  if (a instanceof ObjectId && b instanceof ObjectId) {
    return a.toString() !== b.toString();
  }
});

DiffResult type

TypeScript
type DiffResult = {
  type: 0 | 1 | 2 | 3 | 4; // see the op-type table below
  path: Array<unknown>;    // path to the property; Map entries use the Map key itself
  value?: unknown;         // the new value (present for ADDED, CHANGED, INSERTED)
};

Op-type constants

ValueConstantMeaningApplies to
0DELETEDKey no longer exists (delete obj.k / map.delete(k); on an array index it leaves a hole).objects, Maps, arrays (sparse)
1ADDEDNew key/value (on arrays: assign at index).objects, Maps, Sets, arrays
2CHANGEDValue replaced at the path.all
3INSERTEDInsert value at the index, shifting later elements right (splice(i, 0, v)).arrays only
4REMOVEDRemove the element at the index, shifting later elements left (splice(i, 1)).arrays only
TypeScript
import { DELETED, ADDED, CHANGED, INSERTED, REMOVED } from "@opentf/obj-diff";

diff(a, b).filter((op) => op.type === REMOVED);

An empty path ([]) denotes the root — the entire source was replaced by the target (e.g. comparing an object to null).

Last updated on
Edit this page