or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

comparison-classes.mdcomparison-functions.mdconfiguration.mdformatting.mdindex.md

comparison-classes.mddocs/

0

# Comparison Classes

1

2

tcompare provides direct access to comparison classes for advanced usage scenarios. These classes offer performance benefits when making multiple comparisons and allow for custom comparison logic through inheritance.

3

4

## Class Hierarchy

5

6

```

7

Format

8

└── Same

9

├── Strict

10

├── Has

11

│ ├── HasStrict (uses Strict.prototype.test)

12

│ └── Match

13

│ └── MatchStrict (fails if a==b && a!==b)

14

├── MatchOnly (uses Match.prototype.test)

15

└── MatchOnlyStrict (uses MatchStrict.prototype.test)

16

```

17

18

## Capabilities

19

20

### Base Format Class

21

22

The foundational class for all formatting and comparison operations.

23

24

```typescript { .api }

25

/**

26

* Base formatting class for converting values to strings

27

*/

28

class Format {

29

constructor(obj: any, options?: FormatOptions);

30

31

/** Generate formatted string representation of the object */

32

print(): string;

33

34

/** Check if the object is an array-like structure */

35

isArray(): boolean;

36

37

/** Get object keys for plain objects */

38

getPojoKeys(obj: any): string[];

39

40

/** Get object entries for plain objects */

41

getPojoEntries(obj: any): Array<[string, any]>;

42

}

43

```

44

45

### Same Class

46

47

Base comparison class providing deep equivalence with loose matching.

48

49

```typescript { .api }

50

/**

51

* Base class for all comparison operations - deep equivalence with loose comparison

52

*/

53

class Same extends Format {

54

constructor(obj: any, options: SameOptions);

55

56

/** Boolean indicating whether objects match after calling print() */

57

match: boolean;

58

59

/** Perform the comparison test - returns boolean or 'COMPLEX' for nested comparison */

60

test(): boolean | 'COMPLEX';

61

62

/** Generate diff string and set match property */

63

print(): string;

64

}

65

66

/**

67

* Options for all comparison operations

68

*/

69

interface SameOptions extends FormatOptions {

70

/** The pattern to test against */

71

expect: any;

72

/** Parent comparison object for nested comparisons */

73

parent?: Same;

74

/** Key in parent object */

75

key?: any;

76

/** Key in expected pattern */

77

expectKey?: any;

78

/** Number of lines of context to show in diffs */

79

diffContext?: number;

80

}

81

```

82

83

**Usage Examples:**

84

85

```typescript

86

import { Same } from "tcompare";

87

88

// Direct class usage

89

const comparison = new Same([1, 2, 3], {

90

expect: ["1", "2", "3"],

91

style: "js"

92

});

93

94

const diff = comparison.print();

95

console.log(comparison.match); // true

96

console.log(diff); // Empty string when match is true

97

```

98

99

### Strict Class

100

101

Deep equality comparison without type coercion, extending Same.

102

103

```typescript { .api }

104

/**

105

* Deep equality comparison without type coercion

106

*/

107

class Strict extends Same {

108

constructor(obj: any, options: SameOptions);

109

110

/** Override test method to enforce strict equality */

111

test(): boolean | 'COMPLEX';

112

}

113

```

114

115

**Usage Examples:**

116

117

```typescript

118

import { Strict } from "tcompare";

119

120

const comparison = new Strict([1, 2, 3], {

121

expect: ["1", "2", "3"]

122

});

123

124

console.log(comparison.print());

125

console.log(comparison.match); // false - no type coercion

126

```

127

128

### Has Class

129

130

Subset matching - only tests properties present in the expected pattern.

131

132

```typescript { .api }

133

/**

134

* Subset matching - all pattern fields must exist in object with loose comparison

135

*/

136

class Has extends Same {

137

constructor(obj: any, options: SameOptions);

138

139

/** Override to only compare fields present in expected pattern */

140

getPojoEntries(obj: any): Array<[string, any]>;

141

142

/** Check if structure should be treated as array */

143

isArray(): boolean;

144

}

145

```

146

147

**Usage Examples:**

148

149

```typescript

150

import { Has } from "tcompare";

151

152

const comparison = new Has(

153

{ name: "Alice", age: 25, city: "NYC" },

154

{ expect: { name: "Alice", age: "25" } }

155

);

156

157

console.log(comparison.match); // true - extra 'city' field ignored

158

```

159

160

### HasStrict Class

161

162

Subset matching with strict comparison for primitives.

163

164

```typescript { .api }

165

/**

166

* Subset matching with strict comparison for primitives

167

*/

168

class HasStrict extends Has {

169

constructor(obj: any, options: SameOptions);

170

171

/** Use strict comparison for primitives, loose for objects */

172

test(): boolean | 'COMPLEX';

173

}

174

```

175

176

### Match Class

177

178

Most flexible matching strategy with pattern support.

179

180

```typescript { .api }

181

/**

182

* Flexible pattern matching with support for regex, constructors, and string patterns

183

*/

184

class Match extends Has {

185

constructor(obj: any, options: SameOptions);

186

187

/** Extended test method supporting multiple pattern types */

188

test(): boolean | 'COMPLEX';

189

}

190

```

191

192

**Usage Examples:**

193

194

```typescript

195

import { Match } from "tcompare";

196

197

// Pattern matching with regular expressions

198

const regexMatch = new Match("hello@example.com", {

199

expect: /@example\.com$/

200

});

201

202

// Constructor pattern matching

203

const typeMatch = new Match(42, {

204

expect: Number

205

});

206

207

// String substring matching

208

const stringMatch = new Match("hello world", {

209

expect: "world"

210

});

211

```

212

213

### MatchOnly Class

214

215

Pattern matching with strict object shape requirements.

216

217

```typescript { .api }

218

/**

219

* Uses Match test but requires exact object shape (no extra fields)

220

*/

221

class MatchOnly extends Same {

222

constructor(obj: any, options: SameOptions);

223

224

/** Use Match.prototype.test for comparison logic */

225

test(): boolean | 'COMPLEX';

226

}

227

```

228

229

### MatchStrict Class

230

231

Pattern matching without type coercion.

232

233

```typescript { .api }

234

/**

235

* Like Match but fails on loose equality without strict equality

236

*/

237

class MatchStrict extends Match {

238

constructor(obj: any, options: SameOptions);

239

240

/** Enhanced test that rejects loose-but-not-strict equality */

241

test(): boolean | 'COMPLEX';

242

}

243

```

244

245

### MatchOnlyStrict Class

246

247

Most restrictive matching - strict patterns with exact object shape.

248

249

```typescript { .api }

250

/**

251

* Uses MatchStrict test but requires exact object shape

252

*/

253

class MatchOnlyStrict extends Same {

254

constructor(obj: any, options: SameOptions);

255

256

/** Use MatchStrict.prototype.test for comparison logic */

257

test(): boolean | 'COMPLEX';

258

}

259

```

260

261

## Advanced Usage Patterns

262

263

### Performance Optimization

264

265

When making many comparisons with the same options, instantiate classes directly to avoid function call overhead:

266

267

```typescript

268

import { Same, SameOptions } from "tcompare";

269

270

const options: SameOptions = {

271

expect: { name: String, age: Number },

272

style: "js",

273

diffContext: 5

274

};

275

276

// Reuse options object for multiple comparisons

277

const users = [

278

{ name: "Alice", age: 25 },

279

{ name: "Bob", age: 30 },

280

{ name: "Charlie", age: "invalid" } // Will fail

281

];

282

283

users.forEach(user => {

284

const comparison = new Same(user, { ...options, expect: options.expect });

285

const diff = comparison.print();

286

287

if (!comparison.match) {

288

console.log(`Invalid user: ${diff}`);

289

}

290

});

291

```

292

293

### Custom Comparison Logic

294

295

Extend existing classes to implement custom comparison behavior:

296

297

```typescript

298

import { Match } from "tcompare";

299

300

class EmailMatch extends Match {

301

test(): boolean | 'COMPLEX' {

302

const obj = this.object;

303

const pattern = this.expect;

304

305

// Custom email validation logic

306

if (typeof pattern === 'string' && pattern === 'email') {

307

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

308

return typeof obj === 'string' && emailRegex.test(obj);

309

}

310

311

// Fall back to parent logic

312

return super.test();

313

}

314

}

315

316

// Usage

317

const emailComparison = new EmailMatch("user@example.com", {

318

expect: 'email'

319

});

320

321

console.log(emailComparison.match); // true for valid email

322

```

323

324

### Accessing Internal State

325

326

Classes expose internal properties for advanced inspection:

327

328

```typescript

329

import { Same } from "tcompare";

330

331

const comparison = new Same({ a: 1, b: 2 }, {

332

expect: { a: 1, b: 3 }

333

});

334

335

// Access internal object and expected pattern

336

console.log('Testing:', comparison.object);

337

console.log('Against:', comparison.expect);

338

339

// Generate diff and check match

340

const diff = comparison.print();

341

console.log('Match:', comparison.match);

342

console.log('Diff:', diff);

343

```