0
# Microdiff
1
2
Microdiff is a tiny (<1kb), fast, zero dependency object and array comparison library. It provides a single `diff()` function that computes differences between JavaScript objects and arrays with full TypeScript support. The library is significantly faster than most other deep comparison libraries and handles cyclical references, special object types like Date and RegExp, and NaN values correctly.
3
4
## Package Information
5
6
- **Package Name**: microdiff
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install microdiff`
10
11
## Core Imports
12
13
```typescript
14
import diff from "microdiff";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const diff = require("microdiff").default;
21
```
22
23
Named imports for TypeScript:
24
25
```typescript
26
import diff, {
27
type Difference,
28
type DifferenceCreate,
29
type DifferenceRemove,
30
type DifferenceChange
31
} from "microdiff";
32
```
33
34
## Basic Usage
35
36
```typescript
37
import diff from "microdiff";
38
39
const obj1 = {
40
originalProperty: true,
41
nested: { value: 42 }
42
};
43
const obj2 = {
44
originalProperty: true,
45
newProperty: "new",
46
nested: { value: 100 }
47
};
48
49
const differences = diff(obj1, obj2);
50
console.log(differences);
51
// [
52
// { type: "CREATE", path: ["newProperty"], value: "new" },
53
// { type: "CHANGE", path: ["nested", "value"], value: 100, oldValue: 42 }
54
// ]
55
```
56
57
## Capabilities
58
59
### Object and Array Comparison
60
61
The core `diff` function performs deep comparison between two objects or arrays and returns an array of difference objects describing all changes.
62
63
```typescript { .api }
64
/**
65
* Deep comparison function that computes differences between two objects or arrays
66
* @param obj - First object/array to compare
67
* @param newObj - Second object/array to compare
68
* @param options - Optional configuration object (defaults to { cyclesFix: true })
69
* @returns Array of Difference objects describing changes
70
*/
71
function diff(
72
obj: Record<string, any> | any[],
73
newObj: Record<string, any> | any[],
74
options?: Partial<{ cyclesFix: boolean }>
75
): Difference[];
76
```
77
78
**Usage Examples:**
79
80
```typescript
81
import diff from "microdiff";
82
83
// Basic object comparison
84
const result1 = diff(
85
{ a: 1, b: 2 },
86
{ a: 1, b: 3, c: 4 }
87
);
88
// [
89
// { type: "CHANGE", path: ["b"], value: 3, oldValue: 2 },
90
// { type: "CREATE", path: ["c"], value: 4 }
91
// ]
92
93
// Array comparison
94
const result2 = diff([1, 2, 3], [1, 3, 4]);
95
// [
96
// { type: "CHANGE", path: [1], value: 3, oldValue: 2 },
97
// { type: "CHANGE", path: [2], value: 4, oldValue: 3 }
98
// ]
99
100
// Nested objects
101
const result3 = diff(
102
{ user: { name: "Alice", age: 25 } },
103
{ user: { name: "Alice", age: 26, active: true } }
104
);
105
// [
106
// { type: "CHANGE", path: ["user", "age"], value: 26, oldValue: 25 },
107
// { type: "CREATE", path: ["user", "active"], value: true }
108
// ]
109
110
// Disable cycle detection for performance
111
const result4 = diff(obj1, obj2, { cyclesFix: false });
112
```
113
114
### Cyclical Reference Handling
115
116
By default, microdiff detects and handles cyclical references to prevent infinite loops during comparison.
117
118
```typescript
119
// Cyclical references are handled automatically
120
const obj1 = { a: {} };
121
obj1.a.parent = obj1;
122
123
const obj2 = { a: {} };
124
obj2.a.parent = obj2;
125
126
const result = diff(obj1, obj2); // Returns [] - objects are equivalent
127
```
128
129
### Special Object Type Support
130
131
Microdiff correctly handles special JavaScript object types by comparing their values rather than their internal structure.
132
133
```typescript
134
// Date objects
135
const result1 = diff(
136
{ created: new Date('2023-01-01') },
137
{ created: new Date('2023-01-02') }
138
);
139
// [{ type: "CHANGE", path: ["created"], value: Date('2023-01-02'), oldValue: Date('2023-01-01') }]
140
141
// RegExp objects
142
const result2 = diff(
143
{ pattern: /abc/g },
144
{ pattern: /def/i }
145
);
146
// [{ type: "CHANGE", path: ["pattern"], value: /def/i, oldValue: /abc/g }]
147
```
148
149
## Types
150
151
### Difference Types
152
153
```typescript { .api }
154
/** Union type representing all possible difference operations */
155
type Difference = DifferenceCreate | DifferenceRemove | DifferenceChange;
156
157
/** Represents a CREATE operation (new property added) */
158
interface DifferenceCreate {
159
type: "CREATE";
160
/** Path to the created property as an array of keys */
161
path: (string | number)[];
162
/** Value of the created property */
163
value: any;
164
}
165
166
/** Represents a REMOVE operation (property deleted) */
167
interface DifferenceRemove {
168
type: "REMOVE";
169
/** Path to the removed property as an array of keys */
170
path: (string | number)[];
171
/** Previous value of the removed property */
172
oldValue: any;
173
}
174
175
/** Represents a CHANGE operation (property value modified) */
176
interface DifferenceChange {
177
type: "CHANGE";
178
/** Path to the changed property as an array of keys */
179
path: (string | number)[];
180
/** New value of the changed property */
181
value: any;
182
/** Previous value of the changed property */
183
oldValue: any;
184
}
185
```
186
187
### Understanding Paths
188
189
The `path` property in difference objects provides a hierarchical path to the changed property:
190
191
- For objects: Uses string keys (`["user", "name"]`)
192
- For arrays: Uses numeric indices (`[0, "property"]`)
193
- For nested structures: Combines both (`["users", 1, "profile", "email"]`)
194
195
```typescript
196
// Path examples
197
const obj1 = {
198
users: [
199
{ name: "Alice", profile: { email: "alice@old.com" } }
200
]
201
};
202
203
const obj2 = {
204
users: [
205
{ name: "Alice", profile: { email: "alice@new.com" } }
206
]
207
};
208
209
const result = diff(obj1, obj2);
210
// [{
211
// type: "CHANGE",
212
// path: ["users", 0, "profile", "email"],
213
// value: "alice@new.com",
214
// oldValue: "alice@old.com"
215
// }]
216
```
217
218
## Advanced Features
219
220
### NaN Handling
221
222
Microdiff treats NaN values as equivalent during comparison, which differs from JavaScript's default behavior:
223
224
```typescript
225
const result = diff({ value: NaN }, { value: NaN });
226
// Returns [] - NaN values are considered equal
227
```
228
229
### Performance Optimization
230
231
For objects without cyclical references (like parsed JSON), disable cycle detection for better performance:
232
233
```typescript
234
// ~49% faster when cycles detection is disabled
235
const result = diff(jsonObj1, jsonObj2, { cyclesFix: false });
236
```
237
238
### Platform Support
239
240
Microdiff runs on all modern JavaScript environments:
241
242
- Node.js (CommonJS and ES modules)
243
- Deno: `import diff from "https://deno.land/x/microdiff@1.5.0/index.ts"`
244
- Bun
245
- Web browsers
246
- Service workers
247
- TypeScript projects (includes full type definitions)