or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

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)