or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

complex-validators.mdconfig-utilities.mdindex.mdnative-validators.mdtype-system.md

complex-validators.mddocs/

0

# Complex Validators

1

2

Complex validators provide advanced validation patterns for custom types, enums, collections, and structured objects.

3

4

## Capabilities

5

6

### Custom Validator

7

8

Creates validators with user-defined validation functions for complex business logic.

9

10

```typescript { .api }

11

/**

12

* Creates a custom validator with user-defined validation function

13

* @param validatorFn - Function that returns true if value is valid

14

* @param warnMsg - Optional custom warning message on validation failure

15

* @returns VueTypeDef with custom validation logic

16

*/

17

static custom<T>(

18

validatorFn: ValidatorFunction<T>,

19

warnMsg?: string

20

): VueTypeDef<T>;

21

22

// Standalone function

23

function custom<T>(

24

validatorFn: ValidatorFunction<T>,

25

warnMsg?: string

26

): VueTypeDef<T>;

27

28

// Validator function signature

29

type ValidatorFunction<T> = (

30

value: T,

31

props?: Record<string, unknown>

32

) => boolean;

33

```

34

35

**Usage Examples:**

36

37

```typescript

38

import VueTypes, { custom } from "vue-types";

39

40

// Email validation

41

const email = custom<string>(

42

(value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),

43

'must be a valid email address'

44

);

45

46

// Range validation

47

const percentage = custom<number>(

48

(value) => value >= 0 && value <= 100,

49

'must be between 0 and 100'

50

);

51

52

// Complex object validation

53

const userProfile = custom<{ name: string; age: number }>(

54

(value) => value.name.length > 0 && value.age >= 0,

55

'invalid user profile'

56

);

57

58

// Usage in component

59

export default {

60

props: {

61

userEmail: email.isRequired,

62

completion: percentage.def(0),

63

profile: userProfile.isRequired

64

}

65

};

66

```

67

68

### One Of Validator

69

70

Validates that a value is one of a specific set of allowed values (enum-style validation).

71

72

```typescript { .api }

73

/**

74

* Creates a validator that accepts only specific values

75

* @param arr - Array of allowed values

76

* @returns VueTypeDef that accepts only values from the array

77

*/

78

static oneOf<T extends readonly any[]>(arr: T): VueTypeDef<T[number]>;

79

80

// Standalone function

81

function oneOf<D, T extends readonly D[]>(arr: T): VueTypeDef<T[number]>;

82

```

83

84

**Usage Examples:**

85

86

```typescript

87

import VueTypes, { oneOf } from "vue-types";

88

89

// String enum

90

const status = oneOf(['pending', 'success', 'error'] as const);

91

const theme = oneOf(['light', 'dark', 'auto'] as const);

92

93

// Mixed types

94

const priority = oneOf([1, 2, 3, 'high', 'low'] as const);

95

96

// With symbols

97

const eventType = oneOf([Symbol('click'), Symbol('hover')] as const);

98

99

// Usage in component

100

export default {

101

props: {

102

currentStatus: status.def('pending'),

103

appTheme: theme.isRequired,

104

taskPriority: priority.def(1)

105

}

106

};

107

```

108

109

### One Of Type Validator

110

111

Validates that a value matches one of multiple type definitions.

112

113

```typescript { .api }

114

/**

115

* Creates a validator that accepts values matching any of multiple types

116

* @param arr - Array of type definitions to match against

117

* @returns VueTypeDef that accepts values matching any provided type

118

*/

119

static oneOfType<T extends VueProp<any>[]>(

120

arr: T

121

): VueTypeDef<InferType<T[number]>>;

122

123

// Standalone function

124

function oneOfType<D extends V, U extends VueProp<any>, V = InferType<U>>(

125

arr: U[]

126

): VueTypeDef<D>;

127

```

128

129

**Usage Examples:**

130

131

```typescript

132

import VueTypes, { oneOfType, string, number, object } from "vue-types";

133

134

// String or number

135

const stringOrNumber = oneOfType([string(), number()]);

136

137

// Complex type union

138

const idValue = oneOfType([

139

string(),

140

number(),

141

object<{ type: string; value: any }>()

142

]);

143

144

// With Vue native types

145

const mixedInput = oneOfType([

146

String,

147

Number,

148

VueTypes.shape({ label: string(), value: string() })

149

]);

150

151

// Usage in component

152

export default {

153

props: {

154

id: stringOrNumber.isRequired,

155

value: idValue.def(''),

156

input: mixedInput.isRequired

157

}

158

};

159

```

160

161

### Array Of Validator

162

163

Validates arrays where all elements match a specific type definition.

164

165

```typescript { .api }

166

/**

167

* Creates a validator for arrays with typed elements

168

* @param type - Type definition that all array elements must match

169

* @returns VueTypeDef for arrays of the specified type

170

*/

171

static arrayOf<T extends VueProp<any>>(type: T): VueTypeDef<InferType<T>[]>;

172

173

// Standalone function

174

function arrayOf<T extends VueProp<any>>(type: T): VueTypeDef<InferType<T>[]>;

175

```

176

177

**Usage Examples:**

178

179

```typescript

180

import VueTypes, { arrayOf, string, number, shape } from "vue-types";

181

182

// Array of strings

183

const tags = arrayOf(string());

184

const categories = arrayOf(VueTypes.string);

185

186

// Array of numbers

187

const scores = arrayOf(number()).def(() => []);

188

189

// Array of objects

190

const users = arrayOf(shape({

191

name: string().isRequired,

192

age: number(),

193

email: string()

194

}));

195

196

// Nested arrays

197

const matrix = arrayOf(arrayOf(number()));

198

199

// Usage in component

200

export default {

201

props: {

202

postTags: tags.def(() => []),

203

testScores: scores.isRequired,

204

userList: users.def(() => []),

205

numberMatrix: matrix.def(() => [])

206

}

207

};

208

```

209

210

### Object Of Validator

211

212

Validates objects where all property values match a specific type definition.

213

214

```typescript { .api }

215

/**

216

* Creates a validator for objects with typed property values

217

* @param type - Type definition that all object values must match

218

* @returns VueTypeDef for objects with values of the specified type

219

*/

220

static objectOf<T extends VueProp<any>>(

221

type: T

222

): VueTypeDef<Record<string, InferType<T>>>;

223

224

// Standalone function

225

function objectOf<T extends VueProp<any>>(

226

type: T

227

): VueTypeDef<Record<string, InferType<T>>>;

228

```

229

230

**Usage Examples:**

231

232

```typescript

233

import VueTypes, { objectOf, string, number, arrayOf } from "vue-types";

234

235

// Object with string values

236

const translations = objectOf(string());

237

238

// Object with number values

239

const scores = objectOf(number()).def(() => ({}));

240

241

// Object with complex values

242

const userPreferences = objectOf(arrayOf(string()));

243

244

// Nested structure

245

const categoryItems = objectOf(objectOf(string()));

246

247

// Usage in component

248

export default {

249

props: {

250

i18n: translations.isRequired,

251

gameScores: scores.def(() => ({})),

252

preferences: userPreferences.def(() => ({})),

253

catalog: categoryItems.def(() => ({}))

254

}

255

};

256

```

257

258

### Instance Of Validator

259

260

Validates that values are instances of a specific constructor function or class.

261

262

```typescript { .api }

263

/**

264

* Creates a validator for class instances

265

* @param instanceConstructor - Constructor function to validate against

266

* @returns VueTypeDef for instances of the specified constructor

267

*/

268

static instanceOf<C extends Constructor>(

269

instanceConstructor: C

270

): VueTypeDef<InstanceType<C>>;

271

272

// Standalone function

273

function instanceOf<C extends Constructor>(

274

instanceConstructor: C

275

): VueTypeDef<InstanceType<C>>;

276

277

// Constructor type

278

type Constructor = new (...args: any[]) => any;

279

```

280

281

**Usage Examples:**

282

283

```typescript

284

import VueTypes, { instanceOf } from "vue-types";

285

286

// Built-in classes

287

const timestamp = instanceOf(Date);

288

const pattern = instanceOf(RegExp);

289

const errorInstance = instanceOf(Error);

290

291

// Custom classes

292

class User {

293

constructor(public name: string, public id: number) {}

294

}

295

296

class ApiClient {

297

constructor(private baseUrl: string) {}

298

}

299

300

const user = instanceOf(User);

301

const client = instanceOf(ApiClient);

302

303

// Usage in component

304

export default {

305

props: {

306

createdAt: timestamp.isRequired,

307

validator: pattern.def(() => /.*/),

308

currentUser: user.isRequired,

309

apiClient: client.isRequired

310

}

311

};

312

```

313

314

### Shape Validator

315

316

Validates object structure with defined property types and supports loose validation.

317

318

```typescript { .api }

319

/**

320

* Creates a validator for objects with specific structure

321

* @param obj - Object defining the required structure and property types

322

* @returns VueTypeShape with strict validation and loose mode support

323

*/

324

static shape<T extends object>(obj: {

325

[K in keyof T]: Prop<T[K]> | VueProp<T[K]>

326

}): VueTypeShape<T>;

327

328

// Standalone function

329

function shape<T extends object>(obj: {

330

[K in keyof T]: Prop<T[K]> | VueProp<T[K]>

331

}): VueTypeShape<T>;

332

333

// Shape interfaces

334

interface VueTypeShape<T> extends VueTypeBaseDef<T> {

335

readonly loose: VueTypeLooseShape<T>;

336

}

337

338

interface VueTypeLooseShape<T> extends VueTypeBaseDef<T> {

339

readonly loose: VueTypeLooseShape<T>;

340

readonly _vueTypes_isLoose: true;

341

}

342

```

343

344

**Usage Examples:**

345

346

```typescript

347

import VueTypes, { shape, string, number, bool, arrayOf } from "vue-types";

348

349

// Basic object shape

350

const userShape = shape({

351

name: string().isRequired,

352

age: number(),

353

email: string()

354

});

355

356

// Nested shapes

357

const addressShape = shape({

358

street: string().isRequired,

359

city: string().isRequired,

360

zipCode: string(),

361

country: string().def('US')

362

});

363

364

const userWithAddress = shape({

365

name: string().isRequired,

366

address: addressShape.isRequired,

367

isActive: bool().def(true)

368

});

369

370

// Shape with arrays

371

const blogPost = shape({

372

title: string().isRequired,

373

content: string().isRequired,

374

tags: arrayOf(string()).def(() => []),

375

publishedAt: VueTypes.instanceOf(Date)

376

});

377

378

// Loose shape (allows additional properties)

379

const flexibleConfig = shape({

380

theme: string().def('light'),

381

debug: bool().def(false)

382

}).loose;

383

384

// Usage in component

385

export default {

386

props: {

387

user: userShape.isRequired,

388

profile: userWithAddress.def(() => ({

389

name: '',

390

address: { street: '', city: '' },

391

isActive: true

392

})),

393

post: blogPost.isRequired,

394

settings: flexibleConfig.def(() => ({ theme: 'light', debug: false }))

395

}

396

};

397

```

398

399

## Advanced Patterns

400

401

### Combining Validators

402

403

Complex validation scenarios can be achieved by combining different validators:

404

405

```typescript

406

// Union of specific shapes

407

const notificationSettings = oneOfType([

408

shape({

409

type: oneOf(['email'] as const),

410

address: string().isRequired

411

}),

412

shape({

413

type: oneOf(['sms'] as const),

414

phone: string().isRequired

415

}),

416

shape({

417

type: oneOf(['push'] as const),

418

deviceId: string().isRequired

419

})

420

]);

421

422

// Conditional validation

423

const conditionalField = custom<any>((value, props) => {

424

if (props?.requiresValidation) {

425

return typeof value === 'string' && value.length > 0;

426

}

427

return true;

428

});

429

```

430

431

### Error Handling

432

433

Complex validators provide detailed error messages for debugging:

434

435

```typescript

436

// Custom error messages

437

const strongPassword = custom<string>(

438

(value) => {

439

return value.length >= 8 &&

440

/[A-Z]/.test(value) &&

441

/[a-z]/.test(value) &&

442

/\d/.test(value);

443

},

444

'password must be at least 8 characters with uppercase, lowercase, and numbers'

445

);

446

447

// Shape validation shows specific property errors

448

const userProfile = shape({

449

username: string().validate((value) => value.length >= 3),

450

email: custom<string>((value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))

451

});

452

```

453

454

### TypeScript Integration

455

456

Complex validators maintain full type safety:

457

458

```typescript

459

// Inferred types

460

const user = shape({

461

name: string(),

462

age: number(),

463

isActive: bool()

464

});

465

// TypeScript infers: VueTypeShape<{ name: string; age: number; isActive: boolean }>

466

467

// Generic constraints

468

const apiResponse = shape({

469

data: custom<User[]>((value) => Array.isArray(value)),

470

status: oneOf(['success', 'error'] as const),

471

message: string()

472

});

473

```