or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdbuiltin-types.mdcollection-types.mdindex.mdobject-array-validation.mdprimitive-types.mdtyped-arrays.md

object-array-validation.mddocs/

0

# Object and Array Validation

1

2

Advanced validation for objects and arrays including shape validation, property checking, element validation, and structural constraints.

3

4

## Capabilities

5

6

### Object Validation

7

8

Comprehensive object validation with shape matching, property validation, and instance checking.

9

10

```typescript { .api }

11

/** Object validation predicate */

12

interface ObjectPredicate extends BasePredicate<object> {

13

// Structure validation

14

readonly plain: ObjectPredicate;

15

readonly empty: ObjectPredicate;

16

readonly nonEmpty: ObjectPredicate;

17

18

// Property validation

19

hasKeys(...keys: string[]): ObjectPredicate;

20

hasAnyKeys(...keys: string[]): ObjectPredicate;

21

valuesOfType<T>(predicate: BasePredicate<T>): ObjectPredicate;

22

deepValuesOfType<T>(predicate: Predicate<T>): ObjectPredicate;

23

24

// Shape validation

25

partialShape<S>(shape: S): ObjectPredicate;

26

exactShape<S>(shape: S): ObjectPredicate;

27

deepEqual(expected: object): ObjectPredicate;

28

instanceOf(instance: Function): ObjectPredicate;

29

}

30

31

/** Shape definition for object validation */

32

type Shape = {

33

[key: string]: BasePredicate<any> | Shape;

34

};

35

```

36

37

**Structure Validation Examples:**

38

39

```typescript

40

import ow from 'ow';

41

42

// Structure validation

43

ow({}, ow.object.plain); // Plain object, not class instance

44

ow({}, ow.object.empty); // Empty object

45

ow({ name: 'Alice' }, ow.object.nonEmpty); // Non-empty object

46

47

// Class instance vs plain object

48

class User { constructor(public name: string) {} }

49

ow(new User('Alice'), ow.object.instanceOf(User));

50

ow({ name: 'Alice' }, ow.object.plain);

51

```

52

53

**Property Validation Examples:**

54

55

```typescript

56

import ow from 'ow';

57

58

const user = { name: 'Alice', age: 30, address: { city: 'NYC' } };

59

60

// Property existence (supports dot-notation)

61

ow(user, ow.object.hasKeys('name', 'age'));

62

ow(user, ow.object.hasKeys('address.city'));

63

ow(user, ow.object.hasAnyKeys('name', 'email'));

64

65

// Value type validation

66

ow({ a: 1, b: 2, c: 3 }, ow.object.valuesOfType(ow.number));

67

ow(

68

{ nums: [1, 2], strs: ['a', 'b'] },

69

ow.object.deepValuesOfType(ow.any(ow.array, ow.string, ow.number))

70

);

71

```

72

73

**Shape Validation Examples:**

74

75

```typescript

76

import ow from 'ow';

77

78

// Partial shape - ignores extra properties

79

const userShape = {

80

name: ow.string,

81

age: ow.number.integer.positive

82

};

83

84

ow({ name: 'Alice', age: 30, extra: 'ignored' }, ow.object.partialShape(userShape));

85

86

// Exact shape - fails on extra properties

87

ow({ name: 'Alice', age: 30 }, ow.object.exactShape(userShape));

88

89

// Nested shape validation

90

const nestedShape = {

91

user: {

92

name: ow.string,

93

contacts: {

94

email: ow.optional.string,

95

phone: ow.optional.string

96

}

97

}

98

};

99

100

ow({

101

user: {

102

name: 'Alice',

103

contacts: {

104

email: 'alice@example.com'

105

}

106

}

107

}, ow.object.exactShape(nestedShape));

108

109

// Deep equality

110

ow({ a: 1, b: [2, 3] }, ow.object.deepEqual({ a: 1, b: [2, 3] }));

111

```

112

113

### Array Validation

114

115

Comprehensive array validation with length constraints, element validation, and content checking.

116

117

```typescript { .api }

118

/** Array validation predicate */

119

interface ArrayPredicate extends BasePredicate<unknown[]> {

120

// Length validation

121

length(length: number): ArrayPredicate;

122

minLength(length: number): ArrayPredicate;

123

maxLength(length: number): ArrayPredicate;

124

125

// Content validation

126

startsWith<T>(searchElement: T): ArrayPredicate;

127

endsWith<T>(searchElement: T): ArrayPredicate;

128

includes<T>(...searchElements: T[]): ArrayPredicate;

129

includesAny<T>(...searchElements: T[]): ArrayPredicate;

130

deepEqual<T>(expected: T[]): ArrayPredicate;

131

132

// State validation

133

readonly empty: ArrayPredicate;

134

readonly nonEmpty: ArrayPredicate;

135

136

// Type validation

137

ofType<U>(predicate: BasePredicate<U>): ArrayPredicate;

138

exactShape(predicates: BasePredicate[]): ArrayPredicate;

139

}

140

```

141

142

**Length Validation Examples:**

143

144

```typescript

145

import ow from 'ow';

146

147

// Length constraints

148

ow([1, 2, 3], ow.array.length(3));

149

ow([1, 2], ow.array.minLength(2));

150

ow([1, 2, 3], ow.array.maxLength(5));

151

ow([], ow.array.empty);

152

ow([1], ow.array.nonEmpty);

153

```

154

155

**Content Validation Examples:**

156

157

```typescript

158

import ow from 'ow';

159

160

const numbers = [1, 2, 3, 4, 5];

161

162

// Element position validation

163

ow(numbers, ow.array.startsWith(1));

164

ow(numbers, ow.array.endsWith(5));

165

166

// Content inclusion

167

ow(numbers, ow.array.includes(2, 3, 4));

168

ow(numbers, ow.array.includesAny(2, 10, 20));

169

170

// Deep equality

171

ow([[1, 2], [3, 4]], ow.array.deepEqual([[1, 2], [3, 4]]));

172

```

173

174

**Type Validation Examples:**

175

176

```typescript

177

import ow from 'ow';

178

179

// All elements must match predicate

180

ow([1, 2, 3], ow.array.ofType(ow.number.positive));

181

ow(['a', 'b', 'c'], ow.array.ofType(ow.string.nonEmpty));

182

183

// Mixed type arrays

184

ow([1, 'hello', true], ow.array.ofType(ow.any(ow.number, ow.string, ow.boolean)));

185

186

// Exact shape validation - elements match predicates at same indices

187

ow(['Alice', 30, true], ow.array.exactShape([

188

ow.string,

189

ow.number.integer.positive,

190

ow.boolean

191

]));

192

193

// Array of objects

194

const users = [

195

{ name: 'Alice', age: 30 },

196

{ name: 'Bob', age: 25 }

197

];

198

199

ow(users, ow.array.ofType(ow.object.exactShape({

200

name: ow.string,

201

age: ow.number.integer.positive

202

})));

203

```

204

205

## Advanced Usage Examples

206

207

### Nested Object and Array Validation

208

209

```typescript

210

import ow from 'ow';

211

212

// Complex nested structure

213

const apiResponse = {

214

users: [

215

{

216

id: 1,

217

profile: {

218

name: 'Alice',

219

contacts: ['alice@example.com', '+1-555-0123']

220

},

221

permissions: ['read', 'write']

222

}

223

],

224

meta: {

225

total: 1,

226

page: 1

227

}

228

};

229

230

const responseShape = {

231

users: ow.array.ofType(ow.object.exactShape({

232

id: ow.number.integer.positive,

233

profile: ow.object.exactShape({

234

name: ow.string.nonEmpty,

235

contacts: ow.array.ofType(ow.string.nonEmpty)

236

}),

237

permissions: ow.array.ofType(ow.string.oneOf(['read', 'write', 'admin']))

238

})),

239

meta: ow.object.exactShape({

240

total: ow.number.integer.positive,

241

page: ow.number.integer.positive

242

})

243

};

244

245

ow(apiResponse, ow.object.exactShape(responseShape));

246

```

247

248

### Dynamic Object Validation

249

250

```typescript

251

import ow from 'ow';

252

253

// Validate object with dynamic keys

254

const dynamicObject = {

255

'user:1': { name: 'Alice', active: true },

256

'user:2': { name: 'Bob', active: false }

257

};

258

259

// All keys must match pattern, all values must match shape

260

ow(Object.keys(dynamicObject), ow.array.ofType(ow.string.matches(/^user:\d+$/)));

261

ow(dynamicObject, ow.object.valuesOfType(ow.object.exactShape({

262

name: ow.string,

263

active: ow.boolean

264

})));

265

```

266

267

### Array Transformation Validation

268

269

```typescript

270

import ow from 'ow';

271

272

// Validate transformed arrays

273

const input = ['1', '2', '3'];

274

const numbers = input.map(Number);

275

276

ow(input, ow.array.ofType(ow.string.numeric));

277

ow(numbers, ow.array.ofType(ow.number.integer));

278

```