or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdasync.mdcollections.mdindex.mdnumbers.mdobjects.mdprimitives.mdstrings.mdtyped-arrays.mdvalidation.mdweb-apis.md

validation.mddocs/

0

# Validation and Logic

1

2

Multi-value validation, logical operations, and specialized validation patterns including predicate testing, enum checking, and truthiness validation.

3

4

## Capabilities

5

6

### Multi-value Validation

7

8

Check multiple values against predicates for comprehensive validation.

9

10

```typescript { .api }

11

/**

12

* Check if all values pass the predicate

13

* @param predicate - Function to test each value

14

* @param values - Values to test

15

* @returns True if all values pass predicate

16

*/

17

function isAll(predicate: Predicate, ...values: unknown[]): boolean;

18

19

/**

20

* Check if any value passes any of the predicates

21

* @param predicate - Single predicate or array of predicates

22

* @param values - Values to test

23

* @returns True if any value passes any predicate

24

*/

25

function isAny(predicate: Predicate | Predicate[], ...values: unknown[]): boolean;

26

27

type Predicate = (value: unknown) => boolean;

28

```

29

30

**Usage Examples:**

31

32

```typescript

33

import is from '@sindresorhus/is';

34

35

// Test all values against single predicate

36

is.all(is.string, 'hello', 'world', 'test'); // => true

37

is.all(is.string, 'hello', 42, 'test'); // => false

38

is.all(is.number, 1, 2, 3, 4); // => true

39

40

// Test any value against single predicate

41

is.any(is.string, 42, true, 'hello'); // => true

42

is.any(is.string, 42, true, null); // => false

43

44

// Test any value against multiple predicates

45

is.any([is.string, is.number], {}, true, 'hello'); // => true (string matches)

46

is.any([is.boolean, is.number], 'hello', [], {}); // => false

47

48

// Practical usage

49

function validateUserData(name: unknown, age: unknown, email: unknown) {

50

if (!is.all(is.string, name, email)) {

51

throw new Error('Name and email must be strings');

52

}

53

54

if (!is.number(age)) {

55

throw new Error('Age must be a number');

56

}

57

58

return { name, age, email };

59

}

60

61

// Flexible validation

62

function hasValidId(data: unknown[]) {

63

// Accept either string or number IDs

64

return is.any([is.string, is.number], ...data);

65

}

66

```

67

68

### Truthiness and Falsiness

69

70

Check logical truthiness and falsiness of values.

71

72

```typescript { .api }

73

/**

74

* Check if value is truthy

75

* @param value - Value to check

76

* @returns True if value is truthy

77

*/

78

function isTruthy<T>(value: T | Falsy): value is T;

79

80

/**

81

* Check if value is falsy

82

* @param value - Value to check

83

* @returns True if value is falsy

84

*/

85

function isFalsy(value: unknown): value is Falsy;

86

87

type Falsy = false | 0 | 0n | '' | null | undefined;

88

```

89

90

**Usage Examples:**

91

92

```typescript

93

import is from '@sindresorhus/is';

94

95

// Truthy values

96

is.truthy('hello'); // => true

97

is.truthy(42); // => true

98

is.truthy([]); // => true (arrays are truthy)

99

is.truthy({}); // => true (objects are truthy)

100

101

// Falsy values

102

is.falsy(false); // => true

103

is.falsy(0); // => true

104

is.falsy(0n); // => true

105

is.falsy(''); // => true

106

is.falsy(null); // => true

107

is.falsy(undefined); // => true

108

109

is.falsy('0'); // => false (string '0' is truthy)

110

is.falsy([]); // => false (empty array is truthy)

111

112

// Type guard usage

113

function processValue<T>(value: T | null | undefined) {

114

if (is.truthy(value)) {

115

// value is now typed as T (non-falsy)

116

return value.toString();

117

}

118

return 'No value provided';

119

}

120

121

// Filtering arrays

122

const mixedArray = ['hello', '', 0, 'world', null, 42, false];

123

const truthyValues = mixedArray.filter(is.truthy);

124

console.log(truthyValues); // ['hello', 'world', 42]

125

126

const falsyValues = mixedArray.filter(is.falsy);

127

console.log(falsyValues); // ['', 0, null, false]

128

```

129

130

### Enum Case Validation

131

132

Check if a value is a member of a TypeScript enum.

133

134

```typescript { .api }

135

/**

136

* Check if value is a member of the given enum

137

* @param value - Value to check

138

* @param targetEnum - Enum to check against

139

* @returns True if value is enum member

140

*/

141

function isEnumCase<T = unknown>(value: unknown, targetEnum: T): value is T[keyof T];

142

```

143

144

**Usage Examples:**

145

146

```typescript

147

import is from '@sindresorhus/is';

148

149

enum Direction {

150

Up = 'up',

151

Down = 'down',

152

Left = 'left',

153

Right = 'right'

154

}

155

156

enum Status {

157

Pending = 0,

158

Approved = 1,

159

Rejected = 2

160

}

161

162

is.enumCase('up', Direction); // => true

163

is.enumCase('diagonal', Direction); // => false

164

is.enumCase(1, Status); // => true

165

is.enumCase(3, Status); // => false

166

167

// Type guard usage

168

function processDirection(input: unknown) {

169

if (is.enumCase(input, Direction)) {

170

// input is now typed as Direction

171

switch (input) {

172

case Direction.Up:

173

return 'Moving up';

174

case Direction.Down:

175

return 'Moving down';

176

case Direction.Left:

177

return 'Moving left';

178

case Direction.Right:

179

return 'Moving right';

180

}

181

}

182

throw new Error('Invalid direction');

183

}

184

185

// API response validation

186

function validateStatus(response: { status: unknown }) {

187

if (is.enumCase(response.status, Status)) {

188

return response.status; // Typed as Status

189

}

190

throw new Error('Invalid status in response');

191

}

192

```

193

194

### Direct Instance Checking

195

196

Check if an instance is a direct instance of a class (not inherited).

197

198

```typescript { .api }

199

/**

200

* Check if instance is direct instance of class (not inherited)

201

* @param instance - Instance to check

202

* @param class_ - Class constructor to check against

203

* @returns True if instance is direct instance

204

*/

205

function isDirectInstanceOf<T>(instance: unknown, class_: Class<T>): instance is T;

206

207

type Class<T, Arguments extends unknown[] = any[]> = Constructor<T, Arguments> & {prototype: T};

208

```

209

210

**Usage Examples:**

211

212

```typescript

213

import is from '@sindresorhus/is';

214

215

class Animal {

216

name: string;

217

constructor(name: string) {

218

this.name = name;

219

}

220

}

221

222

class Dog extends Animal {

223

breed: string;

224

constructor(name: string, breed: string) {

225

super(name);

226

this.breed = breed;

227

}

228

}

229

230

const animal = new Animal('Generic');

231

const dog = new Dog('Buddy', 'Golden Retriever');

232

233

// Direct instance checking

234

is.directInstanceOf(animal, Animal); // => true

235

is.directInstanceOf(dog, Animal); // => false (inherited, not direct)

236

is.directInstanceOf(dog, Dog); // => true

237

238

// Compare with regular instanceof

239

console.log(dog instanceof Animal); // => true (inheritance chain)

240

console.log(is.directInstanceOf(dog, Animal)); // => false (direct only)

241

242

// Type guard usage

243

function processAnimal(animal: unknown) {

244

if (is.directInstanceOf(animal, Animal)) {

245

// animal is typed as Animal (not subclass)

246

console.log('Processing base animal:', animal.name);

247

} else if (is.directInstanceOf(animal, Dog)) {

248

// animal is typed as Dog

249

console.log('Processing dog:', animal.name, animal.breed);

250

}

251

}

252

```

253

254

### Property Key Validation

255

256

Check if a value can be used as an object property key.

257

258

```typescript { .api }

259

/**

260

* Check if value can be used as object property key

261

* @param value - Value to check

262

* @returns True if value is valid property key

263

*/

264

function isPropertyKey(value: unknown): value is PropertyKey;

265

266

type PropertyKey = string | number | symbol;

267

```

268

269

**Usage Examples:**

270

271

```typescript

272

import is from '@sindresorhus/is';

273

274

is.propertyKey('key'); // => true

275

is.propertyKey(42); // => true

276

is.propertyKey(Symbol('key')); // => true

277

278

is.propertyKey({}); // => false

279

is.propertyKey(null); // => false

280

is.propertyKey(true); // => false

281

282

// Type guard usage

283

function safeObjectAccess(obj: Record<PropertyKey, unknown>, key: unknown) {

284

if (is.propertyKey(key)) {

285

// key is now typed as PropertyKey

286

return obj[key];

287

}

288

throw new Error('Invalid property key');

289

}

290

291

// Dynamic property setting

292

function setProperty(obj: object, key: unknown, value: unknown) {

293

if (is.propertyKey(key)) {

294

(obj as any)[key] = value;

295

return true;

296

}

297

return false;

298

}

299

300

// Object key filtering

301

function filterValidKeys(keys: unknown[]): PropertyKey[] {

302

return keys.filter(is.propertyKey);

303

}

304

```

305

306

## Usage Patterns

307

308

### Batch Validation

309

310

```typescript

311

import is from '@sindresorhus/is';

312

313

function validateBatch<T>(

314

values: unknown[],

315

predicate: (value: unknown) => value is T

316

): T[] {

317

if (!is.all(predicate, ...values)) {

318

throw new Error('All values must pass validation');

319

}

320

return values as T[];

321

}

322

323

// Usage

324

const stringArray = validateBatch(['a', 'b', 'c'], is.string);

325

const numberArray = validateBatch([1, 2, 3], is.number);

326

327

function validateMixedTypes(values: unknown[]) {

328

const hasStrings = is.any(is.string, ...values);

329

const hasNumbers = is.any(is.number, ...values);

330

331

return {

332

hasStrings,

333

hasNumbers,

334

isHomogeneous: is.all(is.string, ...values) || is.all(is.number, ...values)

335

};

336

}

337

```

338

339

### Configuration Validation

340

341

```typescript

342

import is from '@sindresorhus/is';

343

344

enum LogLevel {

345

Debug = 'debug',

346

Info = 'info',

347

Warn = 'warn',

348

Error = 'error'

349

}

350

351

interface Config {

352

host: string;

353

port: number;

354

logLevel: LogLevel;

355

features: string[];

356

}

357

358

function validateConfig(config: Record<string, unknown>): Config {

359

// Required string fields

360

if (!is.all(is.string, config.host)) {

361

throw new Error('Host must be a string');

362

}

363

364

// Port validation

365

if (!is.number(config.port) || config.port <= 0) {

366

throw new Error('Port must be a positive number');

367

}

368

369

// Enum validation

370

if (!is.enumCase(config.logLevel, LogLevel)) {

371

throw new Error('Invalid log level');

372

}

373

374

// Array validation

375

if (!is.array(config.features, is.string)) {

376

throw new Error('Features must be array of strings');

377

}

378

379

return config as Config;

380

}

381

```

382

383

### Type-safe Filtering

384

385

```typescript

386

import is from '@sindresorhus/is';

387

388

function partitionArray<T>(

389

array: unknown[],

390

predicate: (value: unknown) => value is T

391

): [T[], unknown[]] {

392

const matching: T[] = [];

393

const nonMatching: unknown[] = [];

394

395

for (const item of array) {

396

if (predicate(item)) {

397

matching.push(item);

398

} else {

399

nonMatching.push(item);

400

}

401

}

402

403

return [matching, nonMatching];

404

}

405

406

// Usage

407

const mixedData = ['hello', 42, true, 'world', null, 3.14];

408

const [strings, nonStrings] = partitionArray(mixedData, is.string);

409

const [numbers, nonNumbers] = partitionArray(nonStrings, is.number);

410

411

console.log('Strings:', strings); // ['hello', 'world']

412

console.log('Numbers:', numbers); // [42, 3.14]

413

```

414

415

### Flexible Type Checking

416

417

```typescript

418

import is from '@sindresorhus/is';

419

420

function acceptMultipleTypes(value: unknown): string {

421

if (is.any([is.string, is.number, is.boolean], value)) {

422

return String(value);

423

}

424

425

if (is.any([is.array, is.plainObject], value)) {

426

return JSON.stringify(value);

427

}

428

429

return 'Unknown type';

430

}

431

432

function requireAllFields(data: Record<string, unknown>, ...fields: string[]) {

433

const values = fields.map(field => data[field]);

434

435

if (!is.all(is.truthy, ...values)) {

436

throw new Error(`Missing required fields: ${fields.join(', ')}`);

437

}

438

439

return data;

440

}

441

```

442

443

## Notes

444

445

- `isAll()` requires all values to pass the predicate; fails fast on first failure

446

- `isAny()` with single predicate tests if any value passes; with array tests if any value passes any predicate

447

- `isTruthy()` and `isFalsy()` follow JavaScript truthiness rules exactly

448

- `isEnumCase()` works with both string and numeric enums

449

- `isDirectInstanceOf()` checks prototype chain directly, not inheritance

450

- `isPropertyKey()` validates JavaScript property key types (string, number, symbol)

451

- All validation methods work with TypeScript type guards for compile-time type narrowing

452

- Multi-value validation is efficient for batch operations and configuration validation