
Security News
CVE Volume Surges Past 48,000 in 2025 as WordPress Plugin Ecosystem Drives Growth
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.
@opentf/obj-diff
Advanced tools
The Fast, Accurate, JavaScript Objects Diffing & Patching Library.
Deep Objects Diffing
Patching
Supports comparing custom object types
TypeScript Support
Cross-Platform
Primitives
Objects
{}Install it using your favourite package manager.
npm install @opentf/obj-diff
yarn add @opentf/obj-diff
pnpm add @opentf/obj-diff
bun add @opentf/obj-diff
deno add @opentf/obj-diff
import { diff } from '@opentf/obj-diff';
diff(obj1: object, obj2: object): Array<DiffResult>
type DiffResult = {
t: 0 | 1 | 2; // The type of diff, 0 - Deleted, 1 - Created, 2 - Updated
p: Array<string | number>; // The object path
v?: unknown; // The current value
};
const a = { a: 1, b: 2 };
const b = { a: 2, c: 3 };
diff(a, b);
/*
[
{
t: 2,
p: ["a"],
v: 2,
},
{
t: 0,
p: ["b"],
},
{
t: 1,
p: ["c"],
v: 5,
},
]
*/
const a = [1, 2, 3, 4, 5];
const b = [1, 3, 5];
diff(a, b);
/*
[
{
t: 2,
p: [1],
v: 3,
},
{
t: 2,
p: [2],
v: 5,
},
{
t: 0,
p: [3],
},
{
t: 0,
p: [4],
},
]
*/
const a = {
foo: {
bar: {
a: ["a", "b"],
b: 2,
c: ["x", "y"],
e: 100,
},
},
buzz: "world",
};
const b = {
foo: {
bar: {
a: ["a"],
b: 2,
c: ["x", "y", "z"],
d: "Hello, world!",
},
},
buzz: "fizz",
};
diff(a, b);
/*
[
{
t: 0,
p: ["foo", "bar", "a", 1],
},
{
t: 1,
p: ["foo", "bar", "c", 2],
v: "z",
},
{
t: 0,
p: ["foo", "bar", "e"],
},
{
t: 1,
p: ["foo", "bar", "d"],
v: "Hello, world!",
},
{
t: 2,
p: ["buzz"],
v: "fizz",
},
]
*/
You can apply the diff result onto the original object to get the modified object.
import { diff, patch } from "@opentf/obj-diff";
const a = { a: 1, b: 2 };
const b = { a: 2, c: 3 };
const out = patch(a, diff(a, b));
assert.deepStrictEqual(out, b); // ok
By default, the diff function cannot compare every object types other than the supported list above.
You can extend the default diff function using the diffWith function.
Now you can compare any object types of your own.
import { diffWith } from '@opentf/obj-diff';
diffWith(
obj1: object,
obj2: object,
fn: (a: object, b: object) => boolean | undefined
): Array<DiffResult>
Let us compare the MongoDB bson ObjectId objects.
import { ObjectId } from "bson";
import { diffWith } from "@opentf/obj-diff";
const record1 = {
_id: new ObjectId(),
title: "Article 1",
desc: "The article description.",
};
const record2 = {
_id: new ObjectId(),
title: "Article 1",
desc: "The new article description.",
};
const result = diffWith(record1, record2, (a, b) => {
if (a instanceof ObjectId && b instanceof ObjectId) {
return a.toString() !== b.toString();
}
});
console.log(result);
/*
[
{
t: 2,
p: [ "_id" ],
v: new ObjectId('663088b877dd3c9aaec482d4'),
},
{
t: 2,
p: [ "desc" ],
v: "The new article description.",
}
]
*/
The JSON Patch protocol is complicated in nature. And simply we don't want use it as our existing solution works for most of the projects.
{p: []} in path property?The empty path denotes Root path, and it simply means the entire object was replaced.
For Eg:
diff({}, null); //=> [{t: 2, p: [], v: null}]
┌───┬──────────────────┬─────────┬───────────────────┬────────┬─────────┐
│ │ Task Name │ ops/sec │ Average Time (ns) │ Margin │ Samples │
├───┼──────────────────┼─────────┼───────────────────┼────────┼─────────┤
+ 0 │ diff │ 252,694 │ 3957.346814404028 │ ±1.60% │ 25270 │
│ 1 │ microdiff │ 218,441 │ 4577.892286564301 │ ±0.92% │ 21845 │
│ 2 │ deep-object-diff │ 121,385 │ 8238.188318642591 │ ±1.66% │ 12139 │
│ 3 │ just-diff │ 105,292 │ 9497.35384615396 │ ±1.66% │ 10530 │
│ 4 │ deep-diff │ 160,802 │ 6218.820533549017 │ ±1.59% │ 16081 │
└───┴──────────────────┴─────────┴───────────────────┴────────┴─────────┘
$ bun run build
$ bun benchmark.js
Please read our important articles:
Copyright (c) Thanga Ganapathy (MIT License).
FAQs
The Fast, Accurate, JavaScript Objects Diffing & Patching Library.
We found that @opentf/obj-diff demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.

Security News
Socket CEO Feross Aboukhadijeh joins Insecure Agents to discuss CVE remediation and why supply chain attacks require a different security approach.

Security News
Tailwind Labs laid off 75% of its engineering team after revenue dropped 80%, as LLMs redirect traffic away from documentation where developers discover paid products.