@ibodr/validate 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1108 -0
- package/dist/index.mjs +1112 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +35 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1108 @@
|
|
|
1
|
+
import { IndexKey, JsonValue, MakeUndefinedOptional } from '@ibodr/utils';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A function that validates and returns a value of type T from unknown input.
|
|
5
|
+
* The function should throw a ValidationError if the value is invalid.
|
|
6
|
+
*
|
|
7
|
+
* @param value - The unknown value to validate
|
|
8
|
+
* @returns The validated value of type T
|
|
9
|
+
* @throws \{ValidationError\} When the value doesn't match the expected type
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const stringValidator: ValidatorFn<string> = (value) => {
|
|
13
|
+
* if (typeof value !== 'string') {
|
|
14
|
+
* throw new ValidationError('Expected string')
|
|
15
|
+
* }
|
|
16
|
+
* return value
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
type ValidatorFn<T> = (value: unknown) => T;
|
|
22
|
+
/**
|
|
23
|
+
* A performance-optimized validation function that can use a previously validated value
|
|
24
|
+
* to avoid revalidating unchanged parts of the data structure.
|
|
25
|
+
*
|
|
26
|
+
* @param knownGoodValue - A previously validated value of type In
|
|
27
|
+
* @param value - The unknown value to validate
|
|
28
|
+
* @returns The validated value of type Out
|
|
29
|
+
* @throws ValidationError When the value doesn't match the expected type
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const optimizedValidator: ValidatorUsingKnownGoodVersionFn<User> = (
|
|
33
|
+
* knownGood,
|
|
34
|
+
* newValue
|
|
35
|
+
* ) => {
|
|
36
|
+
* if (Object.is(knownGood, newValue)) return knownGood
|
|
37
|
+
* return fullValidation(newValue)
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
type ValidatorUsingKnownGoodVersionFn<In, Out = In> = (knownGoodValue: In, value: unknown) => Out;
|
|
43
|
+
/**
|
|
44
|
+
* Interface for objects that can validate unknown values and return typed results.
|
|
45
|
+
* This is the core interface implemented by all validators in the validation system.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const customValidator: Validatable<number> = {
|
|
50
|
+
* validate(value) {
|
|
51
|
+
* if (typeof value !== 'number') {
|
|
52
|
+
* throw new ValidationError('Expected number')
|
|
53
|
+
* }
|
|
54
|
+
* return value
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
interface Validatable<T> {
|
|
61
|
+
/**
|
|
62
|
+
* Validates an unknown value and returns it with the correct type.
|
|
63
|
+
*
|
|
64
|
+
* @param value - The unknown value to validate
|
|
65
|
+
* @returns The validated value with type T
|
|
66
|
+
* @throws ValidationError When validation fails
|
|
67
|
+
*/
|
|
68
|
+
validate(value: unknown): T;
|
|
69
|
+
/**
|
|
70
|
+
* Performance-optimized validation that can use a previously validated value
|
|
71
|
+
* to avoid revalidating unchanged parts of the data structure.
|
|
72
|
+
*
|
|
73
|
+
* If the value has not changed but is not referentially equal, the function
|
|
74
|
+
* should return the previous value.
|
|
75
|
+
*
|
|
76
|
+
* @param knownGoodValue - A previously validated value
|
|
77
|
+
* @param newValue - The new value to validate
|
|
78
|
+
* @returns The validated value, potentially reusing the known good value for performance
|
|
79
|
+
* @throws ValidationError When validation fails
|
|
80
|
+
*/
|
|
81
|
+
validateUsingKnownGoodVersion?(knownGoodValue: T, newValue: unknown): T;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Error thrown when validation fails. Provides detailed information about what went wrong
|
|
85
|
+
* and where in the data structure the error occurred.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* try {
|
|
90
|
+
* validator.validate(invalidData)
|
|
91
|
+
* } catch (error) {
|
|
92
|
+
* if (error instanceof ValidationError) {
|
|
93
|
+
* console.log(error.message) // "At users.0.email: Expected valid URL"
|
|
94
|
+
* console.log(error.path) // ['users', 0, 'email']
|
|
95
|
+
* console.log(error.rawMessage) // "Expected valid URL"
|
|
96
|
+
* }
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
* @public
|
|
100
|
+
*/
|
|
101
|
+
declare class ValidationError extends Error {
|
|
102
|
+
readonly rawMessage: string;
|
|
103
|
+
readonly path: ReadonlyArray<number | string>;
|
|
104
|
+
name: string;
|
|
105
|
+
/**
|
|
106
|
+
* Creates a new ValidationError with contextual information about where the error occurred.
|
|
107
|
+
*
|
|
108
|
+
* rawMessage - The raw error message without path information
|
|
109
|
+
* path - Array indicating the location in the data structure where validation failed
|
|
110
|
+
*/
|
|
111
|
+
constructor(rawMessage: string, path?: ReadonlyArray<number | string>);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Utility type that extracts the validated type from a Validatable object.
|
|
115
|
+
* Useful for deriving TypeScript types from validator definitions.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const userValidator = T.object({ name: T.string, age: T.number })
|
|
120
|
+
* type User = TypeOf<typeof userValidator> // { name: string; age: number }
|
|
121
|
+
* ```
|
|
122
|
+
* @public
|
|
123
|
+
*/
|
|
124
|
+
type TypeOf<V extends Validatable<any>> = V extends Validatable<infer T> ? T : never;
|
|
125
|
+
/**
|
|
126
|
+
* The main validator class that implements the Validatable interface. This is the base class
|
|
127
|
+
* for all validators and provides methods for validation, type checking, and composing validators.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* const numberValidator = new Validator((value) => {
|
|
132
|
+
* if (typeof value !== 'number') {
|
|
133
|
+
* throw new ValidationError('Expected number')
|
|
134
|
+
* }
|
|
135
|
+
* return value
|
|
136
|
+
* })
|
|
137
|
+
*
|
|
138
|
+
* const result = numberValidator.validate(42) // Returns 42 as number
|
|
139
|
+
* ```
|
|
140
|
+
* @public
|
|
141
|
+
*/
|
|
142
|
+
declare class Validator<T> implements Validatable<T> {
|
|
143
|
+
readonly validationFn: ValidatorFn<T>;
|
|
144
|
+
readonly validateUsingKnownGoodVersionFn?: ValidatorUsingKnownGoodVersionFn<T> | undefined;
|
|
145
|
+
/** @internal */
|
|
146
|
+
readonly skipSameValueCheck: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Creates a new Validator instance.
|
|
149
|
+
*
|
|
150
|
+
* validationFn - Function that validates and returns a value of type T
|
|
151
|
+
* validateUsingKnownGoodVersionFn - Optional performance-optimized validation function
|
|
152
|
+
* skipSameValueCheck - Internal flag to skip dev check for validators that transform values
|
|
153
|
+
*/
|
|
154
|
+
constructor(validationFn: ValidatorFn<T>, validateUsingKnownGoodVersionFn?: ValidatorUsingKnownGoodVersionFn<T> | undefined,
|
|
155
|
+
/** @internal */
|
|
156
|
+
skipSameValueCheck?: boolean);
|
|
157
|
+
/**
|
|
158
|
+
* Validates an unknown value and returns it with the correct type. The returned value is
|
|
159
|
+
* guaranteed to be referentially equal to the passed value.
|
|
160
|
+
*
|
|
161
|
+
* @param value - The unknown value to validate
|
|
162
|
+
* @returns The validated value with type T
|
|
163
|
+
* @throws ValidationError When validation fails
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* import { T } from '@ibodr/validate'
|
|
167
|
+
*
|
|
168
|
+
* const name = T.string.validate("Alice") // Returns "Alice" as string
|
|
169
|
+
* const title = T.string.validate("") // Returns "" (empty strings are valid)
|
|
170
|
+
*
|
|
171
|
+
* // These will throw ValidationError:
|
|
172
|
+
* T.string.validate(123) // Expected string, got a number
|
|
173
|
+
* T.string.validate(null) // Expected string, got null
|
|
174
|
+
* T.string.validate(undefined) // Expected string, got undefined
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
validate(value: unknown): T;
|
|
178
|
+
/**
|
|
179
|
+
* Performance-optimized validation using a previously validated value. If the new value
|
|
180
|
+
* is referentially equal to the known good value, returns the known good value immediately.
|
|
181
|
+
*
|
|
182
|
+
* @param knownGoodValue - A previously validated value
|
|
183
|
+
* @param newValue - The new value to validate
|
|
184
|
+
* @returns The validated value, potentially reusing the known good value
|
|
185
|
+
* @throws ValidationError When validation fails
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* import { T } from '@ibodr/validate'
|
|
189
|
+
*
|
|
190
|
+
* const userValidator = T.object({
|
|
191
|
+
* name: T.string,
|
|
192
|
+
* settings: T.object({ theme: T.literalEnum('light', 'dark') })
|
|
193
|
+
* })
|
|
194
|
+
*
|
|
195
|
+
* const user = userValidator.validate({ name: "Alice", settings: { theme: "light" } })
|
|
196
|
+
*
|
|
197
|
+
* // Later, with partially changed data:
|
|
198
|
+
* const newData = { name: "Alice", settings: { theme: "dark" } }
|
|
199
|
+
* const updated = userValidator.validateUsingKnownGoodVersion(user, newData)
|
|
200
|
+
* // Only validates the changed 'theme' field for better performance
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
validateUsingKnownGoodVersion(knownGoodValue: T, newValue: unknown): T;
|
|
204
|
+
/**
|
|
205
|
+
* Type guard that checks if a value is valid without throwing an error.
|
|
206
|
+
*
|
|
207
|
+
* @param value - The value to check
|
|
208
|
+
* @returns True if the value is valid, false otherwise
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* import { T } from '@ibodr/validate'
|
|
212
|
+
*
|
|
213
|
+
* function processUserInput(input: unknown) {
|
|
214
|
+
* if (T.string.isValid(input)) {
|
|
215
|
+
* // input is now typed as string within this block
|
|
216
|
+
* return input.toUpperCase()
|
|
217
|
+
* }
|
|
218
|
+
* if (T.number.isValid(input)) {
|
|
219
|
+
* // input is now typed as number within this block
|
|
220
|
+
* return input.toFixed(2)
|
|
221
|
+
* }
|
|
222
|
+
* throw new Error('Expected string or number')
|
|
223
|
+
* }
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
isValid(value: unknown): value is T;
|
|
227
|
+
/**
|
|
228
|
+
* Returns a new validator that also accepts null values.
|
|
229
|
+
*
|
|
230
|
+
* @returns A new validator that accepts T or null
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import { T } from '@ibodr/validate'
|
|
234
|
+
*
|
|
235
|
+
* const assetValidator = T.object({
|
|
236
|
+
* id: T.string,
|
|
237
|
+
* name: T.string,
|
|
238
|
+
* src: T.srcUrl.nullable(), // Can be null if not loaded yet
|
|
239
|
+
* mimeType: T.string.nullable()
|
|
240
|
+
* })
|
|
241
|
+
*
|
|
242
|
+
* const asset = assetValidator.validate({
|
|
243
|
+
* id: "image-123",
|
|
244
|
+
* name: "photo.jpg",
|
|
245
|
+
* src: null, // Valid - asset not loaded yet
|
|
246
|
+
* mimeType: "image/jpeg"
|
|
247
|
+
* })
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
nullable(): Validator<T | null>;
|
|
251
|
+
/**
|
|
252
|
+
* Returns a new validator that also accepts undefined values.
|
|
253
|
+
*
|
|
254
|
+
* @returns A new validator that accepts T or undefined
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* import { T } from '@ibodr/validate'
|
|
258
|
+
*
|
|
259
|
+
* const shapeConfigValidator = T.object({
|
|
260
|
+
* type: T.literal('rectangle'),
|
|
261
|
+
* x: T.number,
|
|
262
|
+
* y: T.number,
|
|
263
|
+
* label: T.string.optional(), // Optional property
|
|
264
|
+
* metadata: T.object({ created: T.string }).optional()
|
|
265
|
+
* })
|
|
266
|
+
*
|
|
267
|
+
* // Both of these are valid:
|
|
268
|
+
* const shape1 = shapeConfigValidator.validate({ type: 'rectangle', x: 0, y: 0 })
|
|
269
|
+
* const shape2 = shapeConfigValidator.validate({
|
|
270
|
+
* type: 'rectangle', x: 0, y: 0, label: "My Shape"
|
|
271
|
+
* })
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
optional(): Validator<T | undefined>;
|
|
275
|
+
/**
|
|
276
|
+
* Creates a new validator by refining this validator with additional logic that can transform
|
|
277
|
+
* the validated value to a new type.
|
|
278
|
+
*
|
|
279
|
+
* @param otherValidationFn - Function that transforms/validates the value to type U
|
|
280
|
+
* @returns A new validator that validates to type U
|
|
281
|
+
* @throws ValidationError When validation or refinement fails
|
|
282
|
+
* @example
|
|
283
|
+
* ```ts
|
|
284
|
+
* import { T, ValidationError } from '@ibodr/validate'
|
|
285
|
+
*
|
|
286
|
+
* // Transform string to ensure it starts with a prefix
|
|
287
|
+
* const prefixedIdValidator = T.string.refine((id) => {
|
|
288
|
+
* return id.startsWith('shape:') ? id : `shape:${id}`
|
|
289
|
+
* })
|
|
290
|
+
*
|
|
291
|
+
* const id1 = prefixedIdValidator.validate("rectangle-123") // Returns "shape:rectangle-123"
|
|
292
|
+
* const id2 = prefixedIdValidator.validate("shape:circle-456") // Returns "shape:circle-456"
|
|
293
|
+
*
|
|
294
|
+
* // Parse and validate JSON strings
|
|
295
|
+
* const jsonValidator = T.string.refine((str) => {
|
|
296
|
+
* try {
|
|
297
|
+
* return JSON.parse(str)
|
|
298
|
+
* } catch {
|
|
299
|
+
* throw new ValidationError('Invalid JSON string')
|
|
300
|
+
* }
|
|
301
|
+
* })
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
refine<U>(otherValidationFn: (value: T) => U): Validator<U>;
|
|
305
|
+
/**
|
|
306
|
+
* Adds an additional validation check without changing the resulting value type.
|
|
307
|
+
* Can be called with just a check function, or with a name for better error messages.
|
|
308
|
+
*
|
|
309
|
+
* @param name - Name for the check (used in error messages)
|
|
310
|
+
* @param checkFn - Function that validates the value (should throw on invalid input)
|
|
311
|
+
* @returns A new validator with the additional check
|
|
312
|
+
* @throws ValidationError When the check fails
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* import { T, ValidationError } from '@ibodr/validate'
|
|
316
|
+
*
|
|
317
|
+
* // Basic check without name
|
|
318
|
+
* const evenNumber = T.number.check((value) => {
|
|
319
|
+
* if (value % 2 !== 0) {
|
|
320
|
+
* throw new ValidationError('Expected even number')
|
|
321
|
+
* }
|
|
322
|
+
* })
|
|
323
|
+
*
|
|
324
|
+
* // Named checks for better error messages in complex validators
|
|
325
|
+
* const shapePositionValidator = T.object({
|
|
326
|
+
* x: T.number.check('finite', (value) => {
|
|
327
|
+
* if (!Number.isFinite(value)) {
|
|
328
|
+
* throw new ValidationError('Position must be finite')
|
|
329
|
+
* }
|
|
330
|
+
* }),
|
|
331
|
+
* y: T.number.check('within-bounds', (value) => {
|
|
332
|
+
* if (value < -10000 || value > 10000) {
|
|
333
|
+
* throw new ValidationError('Position must be within bounds (-10000 to 10000)')
|
|
334
|
+
* }
|
|
335
|
+
* })
|
|
336
|
+
* })
|
|
337
|
+
*
|
|
338
|
+
* // Error will be: "At x (check finite): Position must be finite"
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
check(name: string, checkFn: (value: T) => void): Validator<T>;
|
|
342
|
+
/**
|
|
343
|
+
* Adds an additional validation check without changing the resulting value type.
|
|
344
|
+
*
|
|
345
|
+
* @param checkFn - Function that validates the value (should throw on invalid input)
|
|
346
|
+
* @returns A new validator with the additional check
|
|
347
|
+
* @throws ValidationError When the check fails
|
|
348
|
+
*/
|
|
349
|
+
check(checkFn: (value: T) => void): Validator<T>;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Validator for arrays where each element is validated using the provided item validator.
|
|
353
|
+
* Extends the base Validator class with array-specific validation methods.
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```ts
|
|
357
|
+
* const stringArray = new ArrayOfValidator(T.string)
|
|
358
|
+
* const numbers = stringArray.validate(["a", "b", "c"]) // Returns string[]
|
|
359
|
+
*
|
|
360
|
+
* const userArray = T.arrayOf(T.object({ name: T.string, age: T.number }))
|
|
361
|
+
* ```
|
|
362
|
+
* @public
|
|
363
|
+
*/
|
|
364
|
+
declare class ArrayOfValidator<T> extends Validator<T[]> {
|
|
365
|
+
readonly itemValidator: Validatable<T>;
|
|
366
|
+
/**
|
|
367
|
+
* Creates a new ArrayOfValidator.
|
|
368
|
+
*
|
|
369
|
+
* itemValidator - Validator used to validate each array element
|
|
370
|
+
*/
|
|
371
|
+
constructor(itemValidator: Validatable<T>);
|
|
372
|
+
/**
|
|
373
|
+
* Returns a new validator that ensures the array is not empty.
|
|
374
|
+
*
|
|
375
|
+
* @returns A new validator that rejects empty arrays
|
|
376
|
+
* @throws ValidationError When the array is empty
|
|
377
|
+
* @example
|
|
378
|
+
* ```ts
|
|
379
|
+
* const nonEmptyStrings = T.arrayOf(T.string).nonEmpty()
|
|
380
|
+
* nonEmptyStrings.validate(["hello"]) // Valid
|
|
381
|
+
* nonEmptyStrings.validate([]) // Throws ValidationError
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
nonEmpty(): Validator<T[]>;
|
|
385
|
+
/**
|
|
386
|
+
* Returns a new validator that ensures the array has more than one element.
|
|
387
|
+
*
|
|
388
|
+
* @returns A new validator that requires at least 2 elements
|
|
389
|
+
* @throws ValidationError When the array has 1 or fewer elements
|
|
390
|
+
* @example
|
|
391
|
+
* ```ts
|
|
392
|
+
* const multipleItems = T.arrayOf(T.string).lengthGreaterThan1()
|
|
393
|
+
* multipleItems.validate(["a", "b"]) // Valid
|
|
394
|
+
* multipleItems.validate(["a"]) // Throws ValidationError
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
397
|
+
lengthGreaterThan1(): Validator<T[]>;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Validator for objects with a defined shape. Each property is validated using its corresponding
|
|
401
|
+
* validator from the config object. Can be configured to allow or reject unknown properties.
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* ```ts
|
|
405
|
+
* const userValidator = new ObjectValidator({
|
|
406
|
+
* name: T.string,
|
|
407
|
+
* age: T.number,
|
|
408
|
+
* email: T.string.optional()
|
|
409
|
+
* })
|
|
410
|
+
*
|
|
411
|
+
* const user = userValidator.validate({
|
|
412
|
+
* name: "Alice",
|
|
413
|
+
* age: 25,
|
|
414
|
+
* email: "alice@example.com"
|
|
415
|
+
* })
|
|
416
|
+
* ```
|
|
417
|
+
* @public
|
|
418
|
+
*/
|
|
419
|
+
declare class ObjectValidator<Shape extends object> extends Validator<Shape> {
|
|
420
|
+
readonly config: {
|
|
421
|
+
readonly [K in keyof Shape]: Validatable<Shape[K]>;
|
|
422
|
+
};
|
|
423
|
+
private readonly shouldAllowUnknownProperties;
|
|
424
|
+
/**
|
|
425
|
+
* Creates a new ObjectValidator.
|
|
426
|
+
*
|
|
427
|
+
* config - Object mapping property names to their validators
|
|
428
|
+
* shouldAllowUnknownProperties - Whether to allow properties not defined in config
|
|
429
|
+
*/
|
|
430
|
+
constructor(config: {
|
|
431
|
+
readonly [K in keyof Shape]: Validatable<Shape[K]>;
|
|
432
|
+
}, shouldAllowUnknownProperties?: boolean);
|
|
433
|
+
/**
|
|
434
|
+
* Returns a new validator that allows unknown properties in the validated object.
|
|
435
|
+
*
|
|
436
|
+
* @returns A new ObjectValidator that accepts extra properties
|
|
437
|
+
* @example
|
|
438
|
+
* ```ts
|
|
439
|
+
* const flexibleUser = T.object({ name: T.string }).allowUnknownProperties()
|
|
440
|
+
* flexibleUser.validate({ name: "Alice", extra: "allowed" }) // Valid
|
|
441
|
+
* ```
|
|
442
|
+
*/
|
|
443
|
+
allowUnknownProperties(): ObjectValidator<Shape>;
|
|
444
|
+
/**
|
|
445
|
+
* Creates a new ObjectValidator by extending this validator with additional properties.
|
|
446
|
+
*
|
|
447
|
+
* @param extension - Object mapping new property names to their validators
|
|
448
|
+
* @returns A new ObjectValidator that validates both original and extended properties
|
|
449
|
+
* @example
|
|
450
|
+
* ```ts
|
|
451
|
+
* const baseUser = T.object({ name: T.string, age: T.number })
|
|
452
|
+
* const adminUser = baseUser.extend({
|
|
453
|
+
* permissions: T.arrayOf(T.string),
|
|
454
|
+
* isAdmin: T.boolean
|
|
455
|
+
* })
|
|
456
|
+
* // adminUser validates: { name: string; age: number; permissions: string[]; isAdmin: boolean }
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
extend<Extension extends Record<string, unknown>>(extension: {
|
|
460
|
+
readonly [K in keyof Extension]: Validatable<Extension[K]>;
|
|
461
|
+
}): ObjectValidator<Shape & Extension>;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Configuration type for union validators. Each variant must be a validator that produces
|
|
465
|
+
* an object with the discriminator key set to the variant name.
|
|
466
|
+
*
|
|
467
|
+
* @example
|
|
468
|
+
* ```ts
|
|
469
|
+
* type ShapeConfig = UnionValidatorConfig<'type', {
|
|
470
|
+
* circle: Validatable<{ type: 'circle'; radius: number }>
|
|
471
|
+
* square: Validatable<{ type: 'square'; size: number }>
|
|
472
|
+
* }>
|
|
473
|
+
* ```
|
|
474
|
+
* @public
|
|
475
|
+
*/
|
|
476
|
+
type UnionValidatorConfig<Key extends string, Config> = {
|
|
477
|
+
readonly [Variant in keyof Config]: Validatable<any> & {
|
|
478
|
+
validate(input: any): {
|
|
479
|
+
readonly [K in Key]: Variant;
|
|
480
|
+
};
|
|
481
|
+
};
|
|
482
|
+
};
|
|
483
|
+
/**
|
|
484
|
+
* Validator for discriminated union types. Validates objects that can be one of several variants,
|
|
485
|
+
* distinguished by a discriminator property (key) that indicates which variant the object represents.
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* ```ts
|
|
489
|
+
* const shapeValidator = new UnionValidator('type', {
|
|
490
|
+
* circle: T.object({ type: T.literal('circle'), radius: T.number }),
|
|
491
|
+
* square: T.object({ type: T.literal('square'), size: T.number })
|
|
492
|
+
* }, () => { throw new Error('Unknown shape') }, false)
|
|
493
|
+
*
|
|
494
|
+
* const circle = shapeValidator.validate({ type: 'circle', radius: 5 })
|
|
495
|
+
* // circle is typed as { type: 'circle'; radius: number }
|
|
496
|
+
* ```
|
|
497
|
+
* @public
|
|
498
|
+
*/
|
|
499
|
+
declare class UnionValidator<Key extends string, Config extends UnionValidatorConfig<Key, Config>, UnknownValue = never> extends Validator<TypeOf<Config[keyof Config]> | UnknownValue> {
|
|
500
|
+
private readonly key;
|
|
501
|
+
private readonly config;
|
|
502
|
+
private readonly unknownValueValidation;
|
|
503
|
+
private readonly useNumberKeys;
|
|
504
|
+
/**
|
|
505
|
+
* Creates a new UnionValidator.
|
|
506
|
+
*
|
|
507
|
+
* key - The discriminator property name used to determine the variant
|
|
508
|
+
* config - Object mapping variant names to their validators
|
|
509
|
+
* unknownValueValidation - Function to handle unknown variants
|
|
510
|
+
* useNumberKeys - Whether the discriminator uses number keys instead of strings
|
|
511
|
+
*/
|
|
512
|
+
constructor(key: Key, config: Config, unknownValueValidation: (value: object, variant: string) => UnknownValue, useNumberKeys: boolean);
|
|
513
|
+
private expectObject;
|
|
514
|
+
private getMatchingSchemaAndVariant;
|
|
515
|
+
/**
|
|
516
|
+
* Returns a new UnionValidator that can handle unknown variants using the provided function.
|
|
517
|
+
*
|
|
518
|
+
* @param unknownValueValidation - Function to validate/transform unknown variants
|
|
519
|
+
* @returns A new UnionValidator that accepts unknown variants
|
|
520
|
+
* @example
|
|
521
|
+
* ```ts
|
|
522
|
+
* const shapeValidator = T.union('type', { circle: circleValidator })
|
|
523
|
+
* .validateUnknownVariants((obj, variant) => {
|
|
524
|
+
* console.warn(`Unknown shape type: ${variant}`)
|
|
525
|
+
* return obj as UnknownShape
|
|
526
|
+
* })
|
|
527
|
+
* ```
|
|
528
|
+
*/
|
|
529
|
+
validateUnknownVariants<Unknown>(unknownValueValidation: (value: object, variant: string) => Unknown): UnionValidator<Key, Config, Unknown>;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Validator for dictionary/map objects where both keys and values are validated.
|
|
533
|
+
* Useful for validating objects used as key-value stores.
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```ts
|
|
537
|
+
* const scoreDict = new DictValidator(T.string, T.number)
|
|
538
|
+
* const scores = scoreDict.validate({
|
|
539
|
+
* "alice": 100,
|
|
540
|
+
* "bob": 85,
|
|
541
|
+
* "charlie": 92
|
|
542
|
+
* })
|
|
543
|
+
* // scores is typed as Record<string, number>
|
|
544
|
+
* ```
|
|
545
|
+
* @public
|
|
546
|
+
*/
|
|
547
|
+
declare class DictValidator<Key extends string, Value> extends Validator<Record<Key, Value>> {
|
|
548
|
+
readonly keyValidator: Validatable<Key>;
|
|
549
|
+
readonly valueValidator: Validatable<Value>;
|
|
550
|
+
/**
|
|
551
|
+
* Creates a new DictValidator.
|
|
552
|
+
*
|
|
553
|
+
* keyValidator - Validator for object keys
|
|
554
|
+
* valueValidator - Validator for object values
|
|
555
|
+
*/
|
|
556
|
+
constructor(keyValidator: Validatable<Key>, valueValidator: Validatable<Value>);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Validator that accepts any value without type checking. Useful as a starting point for
|
|
560
|
+
* building custom validations or when you need to accept truly unknown data.
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* ```ts
|
|
564
|
+
* const result = T.unknown.validate(anything) // Returns the value as-is
|
|
565
|
+
* // result is typed as unknown
|
|
566
|
+
* ```
|
|
567
|
+
* @public
|
|
568
|
+
*/
|
|
569
|
+
declare const unknown: Validator<unknown>;
|
|
570
|
+
/**
|
|
571
|
+
* Validator that accepts any value and types it as 'any'. This should generally be avoided
|
|
572
|
+
* as it bypasses type safety, but can be used as an escape hatch for prototyping.
|
|
573
|
+
*
|
|
574
|
+
* @example
|
|
575
|
+
* ```ts
|
|
576
|
+
* const result = T.any.validate(anything) // Returns the value as any
|
|
577
|
+
* // result is typed as any - use with caution!
|
|
578
|
+
* ```
|
|
579
|
+
* @public
|
|
580
|
+
*/
|
|
581
|
+
declare const any: Validator<any>;
|
|
582
|
+
/**
|
|
583
|
+
* Validator that ensures a value is a string.
|
|
584
|
+
*
|
|
585
|
+
* @example
|
|
586
|
+
* ```ts
|
|
587
|
+
* const name = T.string.validate("hello") // Returns "hello" as string
|
|
588
|
+
* T.string.validate(123) // Throws ValidationError: "Expected string, got a number"
|
|
589
|
+
* ```
|
|
590
|
+
* @public
|
|
591
|
+
*/
|
|
592
|
+
declare const string: Validator<string>;
|
|
593
|
+
/**
|
|
594
|
+
* Validator that ensures a value is a finite, non-NaN number. Rejects Infinity, -Infinity, and NaN.
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* ```ts
|
|
598
|
+
* const count = T.number.validate(42) // Returns 42 as number
|
|
599
|
+
* T.number.validate(NaN) // Throws ValidationError: "Expected a number, got NaN"
|
|
600
|
+
* T.number.validate(Infinity) // Throws ValidationError: "Expected a finite number, got Infinity"
|
|
601
|
+
* ```
|
|
602
|
+
* @public
|
|
603
|
+
*/
|
|
604
|
+
declare const number: Validator<number>;
|
|
605
|
+
/**
|
|
606
|
+
* Validator that ensures a value is a non-negative number (\>= 0).
|
|
607
|
+
* Despite the name "positive", this validator accepts zero.
|
|
608
|
+
*
|
|
609
|
+
* @example
|
|
610
|
+
* ```ts
|
|
611
|
+
* const price = T.positiveNumber.validate(29.99) // Returns 29.99
|
|
612
|
+
* const free = T.positiveNumber.validate(0) // Returns 0 (valid)
|
|
613
|
+
* T.positiveNumber.validate(-1) // Throws ValidationError: "Expected a positive number, got -1"
|
|
614
|
+
* ```
|
|
615
|
+
* @public
|
|
616
|
+
*/
|
|
617
|
+
declare const positiveNumber: Validator<number>;
|
|
618
|
+
/**
|
|
619
|
+
* Validator that ensures a value is a positive number (\> 0). Rejects zero and negative numbers.
|
|
620
|
+
*
|
|
621
|
+
* @example
|
|
622
|
+
* ```ts
|
|
623
|
+
* const quantity = T.nonZeroNumber.validate(0.01) // Returns 0.01
|
|
624
|
+
* T.nonZeroNumber.validate(0) // Throws ValidationError: "Expected a non-zero positive number, got 0"
|
|
625
|
+
* T.nonZeroNumber.validate(-5) // Throws ValidationError: "Expected a non-zero positive number, got -5"
|
|
626
|
+
* ```
|
|
627
|
+
* @public
|
|
628
|
+
*/
|
|
629
|
+
declare const nonZeroNumber: Validator<number>;
|
|
630
|
+
/**
|
|
631
|
+
* Validator that ensures a value is a finite, non-zero number. Allows negative numbers.
|
|
632
|
+
* Useful for scale factors that can be negative (for flipping) but not zero.
|
|
633
|
+
*
|
|
634
|
+
* @example
|
|
635
|
+
* ```ts
|
|
636
|
+
* const scale = T.nonZeroFiniteNumber.validate(-1.5) // Returns -1.5 (valid, allows negative)
|
|
637
|
+
* T.nonZeroFiniteNumber.validate(0) // Throws ValidationError: "Expected a non-zero number, got 0"
|
|
638
|
+
* T.nonZeroFiniteNumber.validate(Infinity) // Throws ValidationError
|
|
639
|
+
* ```
|
|
640
|
+
* @public
|
|
641
|
+
*/
|
|
642
|
+
declare const nonZeroFiniteNumber: Validator<number>;
|
|
643
|
+
/**
|
|
644
|
+
* Validator that ensures a value is a number in the unit interval [0, 1].
|
|
645
|
+
* Useful for opacity, percentages expressed as decimals, and other normalized values.
|
|
646
|
+
*
|
|
647
|
+
* @example
|
|
648
|
+
* ```ts
|
|
649
|
+
* const opacity = T.unitInterval.validate(0.5) // Returns 0.5
|
|
650
|
+
* T.unitInterval.validate(0) // Returns 0 (valid)
|
|
651
|
+
* T.unitInterval.validate(1) // Returns 1 (valid)
|
|
652
|
+
* T.unitInterval.validate(1.5) // Throws ValidationError
|
|
653
|
+
* T.unitInterval.validate(-0.1) // Throws ValidationError
|
|
654
|
+
* ```
|
|
655
|
+
* @public
|
|
656
|
+
*/
|
|
657
|
+
declare const unitInterval: Validator<number>;
|
|
658
|
+
/**
|
|
659
|
+
* Validator that ensures a value is an integer (whole number).
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```ts
|
|
663
|
+
* const count = T.integer.validate(42) // Returns 42
|
|
664
|
+
* T.integer.validate(3.14) // Throws ValidationError: "Expected an integer, got 3.14"
|
|
665
|
+
* T.integer.validate(-5) // Returns -5 (negative integers are valid)
|
|
666
|
+
* ```
|
|
667
|
+
* @public
|
|
668
|
+
*/
|
|
669
|
+
declare const integer: Validator<number>;
|
|
670
|
+
/**
|
|
671
|
+
* Validator that ensures a value is a non-negative integer (\>= 0).
|
|
672
|
+
* Despite the name "positive", this validator accepts zero.
|
|
673
|
+
*
|
|
674
|
+
* @example
|
|
675
|
+
* ```ts
|
|
676
|
+
* const index = T.positiveInteger.validate(5) // Returns 5
|
|
677
|
+
* const start = T.positiveInteger.validate(0) // Returns 0 (valid)
|
|
678
|
+
* T.positiveInteger.validate(-1) // Throws ValidationError: "Expected a positive integer, got -1"
|
|
679
|
+
* T.positiveInteger.validate(3.14) // Throws ValidationError: "Expected an integer, got 3.14"
|
|
680
|
+
* ```
|
|
681
|
+
* @public
|
|
682
|
+
*/
|
|
683
|
+
declare const positiveInteger: Validator<number>;
|
|
684
|
+
/**
|
|
685
|
+
* Validator that ensures a value is a positive integer (\> 0). Rejects zero and negative integers.
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* ```ts
|
|
689
|
+
* const itemCount = T.nonZeroInteger.validate(1) // Returns 1
|
|
690
|
+
* T.nonZeroInteger.validate(0) // Throws ValidationError: "Expected a non-zero positive integer, got 0"
|
|
691
|
+
* T.nonZeroInteger.validate(-5) // Throws ValidationError: "Expected a non-zero positive integer, got -5"
|
|
692
|
+
* ```
|
|
693
|
+
* @public
|
|
694
|
+
*/
|
|
695
|
+
declare const nonZeroInteger: Validator<number>;
|
|
696
|
+
/**
|
|
697
|
+
* Validator that ensures a value is a boolean.
|
|
698
|
+
*
|
|
699
|
+
* @example
|
|
700
|
+
* ```ts
|
|
701
|
+
* const isActive = T.boolean.validate(true) // Returns true
|
|
702
|
+
* const isEnabled = T.boolean.validate(false) // Returns false
|
|
703
|
+
* T.boolean.validate("true") // Throws ValidationError: "Expected boolean, got a string"
|
|
704
|
+
* ```
|
|
705
|
+
* @public
|
|
706
|
+
*/
|
|
707
|
+
declare const boolean: Validator<boolean>;
|
|
708
|
+
/**
|
|
709
|
+
* Validator that ensures a value is a bigint.
|
|
710
|
+
*
|
|
711
|
+
* @example
|
|
712
|
+
* ```ts
|
|
713
|
+
* const largeNumber = T.bigint.validate(123n) // Returns 123n
|
|
714
|
+
* T.bigint.validate(123) // Throws ValidationError: "Expected bigint, got a number"
|
|
715
|
+
* ```
|
|
716
|
+
* @public
|
|
717
|
+
*/
|
|
718
|
+
declare const bigint: Validator<bigint>;
|
|
719
|
+
/**
|
|
720
|
+
* Creates a validator that only accepts a specific literal value.
|
|
721
|
+
*
|
|
722
|
+
* @param expectedValue - The exact value that must be matched
|
|
723
|
+
* @returns A validator that only accepts the specified literal value
|
|
724
|
+
* @throws ValidationError When the value doesn't match the expected literal
|
|
725
|
+
* @example
|
|
726
|
+
* ```ts
|
|
727
|
+
* const trueValidator = T.literal(true)
|
|
728
|
+
* trueValidator.validate(true) // Returns true
|
|
729
|
+
* trueValidator.validate(false) // Throws ValidationError
|
|
730
|
+
*
|
|
731
|
+
* const statusValidator = T.literal("active")
|
|
732
|
+
* statusValidator.validate("active") // Returns "active"
|
|
733
|
+
* statusValidator.validate("inactive") // Throws ValidationError
|
|
734
|
+
* ```
|
|
735
|
+
* @public
|
|
736
|
+
*/
|
|
737
|
+
declare function literal<T extends string | number | boolean>(expectedValue: T): Validator<T>;
|
|
738
|
+
/**
|
|
739
|
+
* Validator that ensures a value is an array. Does not validate the contents of the array.
|
|
740
|
+
* Use T.arrayOf() to validate both the array structure and its contents.
|
|
741
|
+
*
|
|
742
|
+
* @example
|
|
743
|
+
* ```ts
|
|
744
|
+
* const items = T.array.validate([1, "hello", true]) // Returns unknown[]
|
|
745
|
+
* T.array.validate("not array") // Throws ValidationError: "Expected an array, got a string"
|
|
746
|
+
*
|
|
747
|
+
* // For typed arrays, use T.arrayOf:
|
|
748
|
+
* const numbers = T.arrayOf(T.number).validate([1, 2, 3]) // Returns number[]
|
|
749
|
+
* ```
|
|
750
|
+
* @public
|
|
751
|
+
*/
|
|
752
|
+
declare const array: Validator<unknown[]>;
|
|
753
|
+
/**
|
|
754
|
+
* Creates a validator for arrays where each element is validated using the provided validator.
|
|
755
|
+
*
|
|
756
|
+
* @param itemValidator - Validator to use for each array element
|
|
757
|
+
* @returns An ArrayOfValidator that validates both array structure and element types
|
|
758
|
+
* @throws ValidationError When the value is not an array or when any element is invalid
|
|
759
|
+
* @example
|
|
760
|
+
* ```ts
|
|
761
|
+
* const numberArray = T.arrayOf(T.number)
|
|
762
|
+
* numberArray.validate([1, 2, 3]) // Returns number[]
|
|
763
|
+
* numberArray.validate([1, "2", 3]) // Throws ValidationError at index 1
|
|
764
|
+
*
|
|
765
|
+
* const userArray = T.arrayOf(T.object({ name: T.string, age: T.number }))
|
|
766
|
+
* ```
|
|
767
|
+
* @public
|
|
768
|
+
*/
|
|
769
|
+
declare function arrayOf<T>(itemValidator: Validatable<T>): ArrayOfValidator<T>;
|
|
770
|
+
/**
|
|
771
|
+
* Validator that ensures a value is an object (non-null, non-array). Does not validate
|
|
772
|
+
* the properties of the object.
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* ```ts
|
|
776
|
+
* const obj = T.unknownObject.validate({ any: "properties" }) // Returns Record<string, unknown>
|
|
777
|
+
* T.unknownObject.validate(null) // Throws ValidationError: "Expected object, got null"
|
|
778
|
+
* T.unknownObject.validate([1, 2, 3]) // Throws ValidationError: "Expected object, got an array"
|
|
779
|
+
* ```
|
|
780
|
+
* @public
|
|
781
|
+
*/
|
|
782
|
+
declare const unknownObject: Validator<Record<string, unknown>>;
|
|
783
|
+
/**
|
|
784
|
+
* Creates a validator for objects with a defined shape. Each property is validated using
|
|
785
|
+
* its corresponding validator from the config object.
|
|
786
|
+
*
|
|
787
|
+
* @param config - Object mapping property names to their validators
|
|
788
|
+
* @returns An ObjectValidator that validates the object structure and all properties
|
|
789
|
+
* @throws ValidationError When the value is not an object or when any property is invalid
|
|
790
|
+
* @example
|
|
791
|
+
* ```ts
|
|
792
|
+
* const userValidator = T.object({
|
|
793
|
+
* name: T.string,
|
|
794
|
+
* age: T.number,
|
|
795
|
+
* email: T.string.optional(),
|
|
796
|
+
* isActive: T.boolean
|
|
797
|
+
* })
|
|
798
|
+
*
|
|
799
|
+
* const user = userValidator.validate({
|
|
800
|
+
* name: "Alice",
|
|
801
|
+
* age: 25,
|
|
802
|
+
* email: "alice@example.com",
|
|
803
|
+
* isActive: true
|
|
804
|
+
* })
|
|
805
|
+
* // user is typed with full type safety
|
|
806
|
+
* ```
|
|
807
|
+
* @public
|
|
808
|
+
*/
|
|
809
|
+
declare function object<Shape extends object>(config: {
|
|
810
|
+
readonly [K in keyof Shape]: Validatable<Shape[K]>;
|
|
811
|
+
}): ObjectValidator<MakeUndefinedOptional<Shape>>;
|
|
812
|
+
/**
|
|
813
|
+
* Validator that ensures a value is valid JSON (string, number, boolean, null, array, or plain object).
|
|
814
|
+
* Rejects functions, undefined, symbols, and other non-JSON values.
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* ```ts
|
|
818
|
+
* const data = T.jsonValue.validate({ name: "Alice", scores: [1, 2, 3], active: true })
|
|
819
|
+
* T.jsonValue.validate(undefined) // Throws ValidationError
|
|
820
|
+
* T.jsonValue.validate(() => {}) // Throws ValidationError
|
|
821
|
+
* ```
|
|
822
|
+
* @public
|
|
823
|
+
*/
|
|
824
|
+
declare const jsonValue: Validator<JsonValue>;
|
|
825
|
+
/**
|
|
826
|
+
* Creates a validator for JSON dictionaries (objects with string keys and JSON-serializable values).
|
|
827
|
+
*
|
|
828
|
+
* @returns A DictValidator that validates string keys and JSON values
|
|
829
|
+
* @throws ValidationError When keys are not strings or values are not JSON-serializable
|
|
830
|
+
* @example
|
|
831
|
+
* ```ts
|
|
832
|
+
* const config = T.jsonDict().validate({
|
|
833
|
+
* "setting1": "value",
|
|
834
|
+
* "setting2": 42,
|
|
835
|
+
* "setting3": ["a", "b", "c"],
|
|
836
|
+
* "setting4": { nested: true }
|
|
837
|
+
* })
|
|
838
|
+
* ```
|
|
839
|
+
* @public
|
|
840
|
+
*/
|
|
841
|
+
declare function jsonDict(): DictValidator<string, JsonValue>;
|
|
842
|
+
/**
|
|
843
|
+
* Creates a validator for dictionary objects where both keys and values are validated.
|
|
844
|
+
* Useful for validating objects used as key-value maps.
|
|
845
|
+
*
|
|
846
|
+
* @param keyValidator - Validator for object keys
|
|
847
|
+
* @param valueValidator - Validator for object values
|
|
848
|
+
* @returns A DictValidator that validates all keys and values
|
|
849
|
+
* @throws ValidationError When any key or value is invalid
|
|
850
|
+
* @example
|
|
851
|
+
* ```ts
|
|
852
|
+
* const scores = T.dict(T.string, T.number)
|
|
853
|
+
* scores.validate({ "alice": 100, "bob": 85 }) // Valid
|
|
854
|
+
*
|
|
855
|
+
* const userPrefs = T.dict(T.string, T.object({
|
|
856
|
+
* theme: T.literalEnum('light', 'dark'),
|
|
857
|
+
* notifications: T.boolean
|
|
858
|
+
* }))
|
|
859
|
+
* ```
|
|
860
|
+
* @public
|
|
861
|
+
*/
|
|
862
|
+
declare function dict<Key extends string, Value>(keyValidator: Validatable<Key>, valueValidator: Validatable<Value>): DictValidator<Key, Value>;
|
|
863
|
+
/**
|
|
864
|
+
* Creates a validator for discriminated union types. Validates objects that can be one of
|
|
865
|
+
* several variants, distinguished by a discriminator property.
|
|
866
|
+
*
|
|
867
|
+
* @param key - The discriminator property name used to determine the variant
|
|
868
|
+
* @param config - Object mapping variant names to their validators
|
|
869
|
+
* @returns A UnionValidator that validates based on the discriminator value
|
|
870
|
+
* @throws ValidationError When the discriminator is invalid or the variant validation fails
|
|
871
|
+
* @example
|
|
872
|
+
* ```ts
|
|
873
|
+
* const shapeValidator = T.union('type', {
|
|
874
|
+
* circle: T.object({ type: T.literal('circle'), radius: T.number }),
|
|
875
|
+
* square: T.object({ type: T.literal('square'), size: T.number }),
|
|
876
|
+
* triangle: T.object({ type: T.literal('triangle'), base: T.number, height: T.number })
|
|
877
|
+
* })
|
|
878
|
+
*
|
|
879
|
+
* const circle = shapeValidator.validate({ type: 'circle', radius: 5 })
|
|
880
|
+
* // circle is typed as { type: 'circle'; radius: number }
|
|
881
|
+
* ```
|
|
882
|
+
* @public
|
|
883
|
+
*/
|
|
884
|
+
declare function union<Key extends string, Config extends UnionValidatorConfig<Key, Config>>(key: Key, config: Config): UnionValidator<Key, Config>;
|
|
885
|
+
/**
|
|
886
|
+
* Creates a validator for discriminated union types using number discriminators instead of strings.
|
|
887
|
+
* This is an internal function used for specific cases where numeric discriminators are needed.
|
|
888
|
+
*
|
|
889
|
+
* @param key - The discriminator property name used to determine the variant
|
|
890
|
+
* @param config - Object mapping variant names to their validators
|
|
891
|
+
* @returns A UnionValidator that validates based on numeric discriminator values
|
|
892
|
+
* @throws ValidationError When the discriminator is invalid or the variant validation fails
|
|
893
|
+
* @internal
|
|
894
|
+
*/
|
|
895
|
+
declare function numberUnion<Key extends string, Config extends UnionValidatorConfig<Key, Config>>(key: Key, config: Config): UnionValidator<Key, Config>;
|
|
896
|
+
/**
|
|
897
|
+
* Creates a validator for named model objects with enhanced error reporting. The model name
|
|
898
|
+
* will be included in error messages to provide better debugging context.
|
|
899
|
+
*
|
|
900
|
+
* @param name - The name of the model (used in error messages)
|
|
901
|
+
* @param validator - The validator for the model structure
|
|
902
|
+
* @returns A Validator with enhanced error reporting that includes the model name
|
|
903
|
+
* @throws ValidationError With model name context when validation fails
|
|
904
|
+
* @example
|
|
905
|
+
* ```ts
|
|
906
|
+
* const userModel = T.model('User', T.object({
|
|
907
|
+
* id: T.string,
|
|
908
|
+
* name: T.string,
|
|
909
|
+
* email: T.linkUrl
|
|
910
|
+
* }))
|
|
911
|
+
*
|
|
912
|
+
* // Error message will be: "At User.email: Expected a valid url, got 'invalid-email'"
|
|
913
|
+
* ```
|
|
914
|
+
* @public
|
|
915
|
+
*/
|
|
916
|
+
declare function model<T extends {
|
|
917
|
+
readonly id: string;
|
|
918
|
+
}>(name: string, validator: Validatable<T>): Validator<T>;
|
|
919
|
+
/**
|
|
920
|
+
* Creates a validator that only accepts values from a given Set of allowed values.
|
|
921
|
+
*
|
|
922
|
+
* @param values - Set containing the allowed values
|
|
923
|
+
* @returns A validator that only accepts values from the provided set
|
|
924
|
+
* @throws ValidationError When the value is not in the allowed set
|
|
925
|
+
* @example
|
|
926
|
+
* ```ts
|
|
927
|
+
* const allowedColors = new Set(['red', 'green', 'blue'] as const)
|
|
928
|
+
* const colorValidator = T.setEnum(allowedColors)
|
|
929
|
+
* colorValidator.validate('red') // Returns 'red'
|
|
930
|
+
* colorValidator.validate('yellow') // Throws ValidationError
|
|
931
|
+
* ```
|
|
932
|
+
* @public
|
|
933
|
+
*/
|
|
934
|
+
declare function setEnum<T>(values: ReadonlySet<T>): Validator<T>;
|
|
935
|
+
/**
|
|
936
|
+
* Creates a validator that accepts either the validated type or undefined.
|
|
937
|
+
*
|
|
938
|
+
* @param validator - The base validator to make optional
|
|
939
|
+
* @returns A validator that accepts T or undefined
|
|
940
|
+
* @example
|
|
941
|
+
* ```ts
|
|
942
|
+
* const optionalString = T.optional(T.string)
|
|
943
|
+
* optionalString.validate("hello") // Returns "hello"
|
|
944
|
+
* optionalString.validate(undefined) // Returns undefined
|
|
945
|
+
* optionalString.validate(null) // Throws ValidationError
|
|
946
|
+
* ```
|
|
947
|
+
* @public
|
|
948
|
+
*/
|
|
949
|
+
declare function optional<T>(validator: Validatable<T>): Validator<T | undefined>;
|
|
950
|
+
/**
|
|
951
|
+
* Creates a validator that accepts either the validated type or null.
|
|
952
|
+
*
|
|
953
|
+
* @param validator - The base validator to make nullable
|
|
954
|
+
* @returns A validator that accepts T or null
|
|
955
|
+
* @example
|
|
956
|
+
* ```ts
|
|
957
|
+
* const nullableString = T.nullable(T.string)
|
|
958
|
+
* nullableString.validate("hello") // Returns "hello"
|
|
959
|
+
* nullableString.validate(null) // Returns null
|
|
960
|
+
* nullableString.validate(undefined) // Throws ValidationError
|
|
961
|
+
* ```
|
|
962
|
+
* @public
|
|
963
|
+
*/
|
|
964
|
+
declare function nullable<T>(validator: Validatable<T>): Validator<T | null>;
|
|
965
|
+
/**
|
|
966
|
+
* Creates a validator that only accepts one of the provided literal values.
|
|
967
|
+
* This is a convenience function that creates a setEnum from the provided values.
|
|
968
|
+
*
|
|
969
|
+
* @param values - The allowed literal values
|
|
970
|
+
* @returns A validator that only accepts the provided literal values
|
|
971
|
+
* @throws ValidationError When the value is not one of the allowed literals
|
|
972
|
+
* @example
|
|
973
|
+
* ```ts
|
|
974
|
+
* const themeValidator = T.literalEnum('light', 'dark', 'auto')
|
|
975
|
+
* themeValidator.validate('light') // Returns 'light'
|
|
976
|
+
* themeValidator.validate('blue') // Throws ValidationError: Expected "light" or "dark" or "auto", got blue
|
|
977
|
+
* ```
|
|
978
|
+
* @public
|
|
979
|
+
*/
|
|
980
|
+
declare function literalEnum<const Values extends readonly unknown[]>(...values: Values): Validator<Values[number]>;
|
|
981
|
+
/**
|
|
982
|
+
* Validator for URLs that are safe to use as user-facing links. Accepts http, https, and mailto protocols.
|
|
983
|
+
* This validator provides security by rejecting potentially dangerous protocols like javascript:.
|
|
984
|
+
*
|
|
985
|
+
* @example
|
|
986
|
+
* ```ts
|
|
987
|
+
* const link = T.linkUrl.validate("https://example.com") // Valid
|
|
988
|
+
* const email = T.linkUrl.validate("mailto:user@example.com") // Valid
|
|
989
|
+
* T.linkUrl.validate("") // Valid (empty string allowed)
|
|
990
|
+
* T.linkUrl.validate("javascript:alert(1)") // Throws ValidationError (unsafe protocol)
|
|
991
|
+
* ```
|
|
992
|
+
* @public
|
|
993
|
+
*/
|
|
994
|
+
declare const linkUrl: Validator<string>;
|
|
995
|
+
/**
|
|
996
|
+
* Validator for URLs that are safe to use as asset sources. Accepts http, https, data, and asset protocols.
|
|
997
|
+
* The asset: protocol refers to tldraw's local IndexedDB object store.
|
|
998
|
+
*
|
|
999
|
+
* @example
|
|
1000
|
+
* ```ts
|
|
1001
|
+
* const imageUrl = T.srcUrl.validate("https://example.com/image.png") // Valid
|
|
1002
|
+
* const dataUrl = T.srcUrl.validate("data:image/png;base64,iVBORw0...") // Valid
|
|
1003
|
+
* const assetUrl = T.srcUrl.validate("asset:abc123") // Valid (local asset reference)
|
|
1004
|
+
* T.srcUrl.validate("") // Valid (empty string allowed)
|
|
1005
|
+
* ```
|
|
1006
|
+
* @public
|
|
1007
|
+
*/
|
|
1008
|
+
declare const srcUrl: Validator<string>;
|
|
1009
|
+
/**
|
|
1010
|
+
* Validator for HTTP and HTTPS URLs only. Rejects all other protocols.
|
|
1011
|
+
*
|
|
1012
|
+
* @example
|
|
1013
|
+
* ```ts
|
|
1014
|
+
* const apiUrl = T.httpUrl.validate("https://api.example.com") // Valid
|
|
1015
|
+
* const httpUrl = T.httpUrl.validate("http://localhost:3000") // Valid
|
|
1016
|
+
* T.httpUrl.validate("") // Valid (empty string allowed)
|
|
1017
|
+
* T.httpUrl.validate("ftp://files.example.com") // Throws ValidationError (not http/https)
|
|
1018
|
+
* ```
|
|
1019
|
+
* @public
|
|
1020
|
+
*/
|
|
1021
|
+
declare const httpUrl: Validator<string>;
|
|
1022
|
+
/**
|
|
1023
|
+
* Validator for IndexKey values used in tldraw's indexing system. An IndexKey is a string
|
|
1024
|
+
* that meets specific format requirements for use as a database index.
|
|
1025
|
+
*
|
|
1026
|
+
* @throws ValidationError When the string is not a valid IndexKey format
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```ts
|
|
1029
|
+
* const key = T.indexKey.validate("valid_index_key") // Returns IndexKey
|
|
1030
|
+
* T.indexKey.validate("invalid key!") // Throws ValidationError (invalid format)
|
|
1031
|
+
* ```
|
|
1032
|
+
* @public
|
|
1033
|
+
*/
|
|
1034
|
+
declare const indexKey: Validator<IndexKey>;
|
|
1035
|
+
/**
|
|
1036
|
+
* Creates a validator that accepts values matching either of two validators.
|
|
1037
|
+
* Tries the first validator, and if it fails, tries the second validator.
|
|
1038
|
+
*
|
|
1039
|
+
* @param v1 - The first validator to try
|
|
1040
|
+
* @param v2 - The second validator to try if the first fails
|
|
1041
|
+
* @returns A validator that accepts values matching either validator
|
|
1042
|
+
* @throws ValidationError When the value matches neither validator (throws error from v2)
|
|
1043
|
+
* @example
|
|
1044
|
+
* ```ts
|
|
1045
|
+
* const stringOrNumber = T.or(T.string, T.number)
|
|
1046
|
+
* stringOrNumber.validate("hello") // Returns "hello" as string
|
|
1047
|
+
* stringOrNumber.validate(42) // Returns 42 as number
|
|
1048
|
+
* stringOrNumber.validate(true) // Throws ValidationError from number validator
|
|
1049
|
+
* ```
|
|
1050
|
+
* @public
|
|
1051
|
+
*/
|
|
1052
|
+
declare function or<T1, T2>(v1: Validatable<T1>, v2: Validatable<T2>): Validator<T1 | T2>;
|
|
1053
|
+
|
|
1054
|
+
type validation_ArrayOfValidator<T> = ArrayOfValidator<T>;
|
|
1055
|
+
declare const validation_ArrayOfValidator: typeof ArrayOfValidator;
|
|
1056
|
+
type validation_DictValidator<Key extends string, Value> = DictValidator<Key, Value>;
|
|
1057
|
+
declare const validation_DictValidator: typeof DictValidator;
|
|
1058
|
+
type validation_ObjectValidator<Shape extends object> = ObjectValidator<Shape>;
|
|
1059
|
+
declare const validation_ObjectValidator: typeof ObjectValidator;
|
|
1060
|
+
type validation_TypeOf<V extends Validatable<any>> = TypeOf<V>;
|
|
1061
|
+
type validation_UnionValidator<Key extends string, Config extends UnionValidatorConfig<Key, Config>, UnknownValue = never> = UnionValidator<Key, Config, UnknownValue>;
|
|
1062
|
+
declare const validation_UnionValidator: typeof UnionValidator;
|
|
1063
|
+
type validation_UnionValidatorConfig<Key extends string, Config> = UnionValidatorConfig<Key, Config>;
|
|
1064
|
+
type validation_Validatable<T> = Validatable<T>;
|
|
1065
|
+
type validation_ValidationError = ValidationError;
|
|
1066
|
+
declare const validation_ValidationError: typeof ValidationError;
|
|
1067
|
+
type validation_Validator<T> = Validator<T>;
|
|
1068
|
+
declare const validation_Validator: typeof Validator;
|
|
1069
|
+
type validation_ValidatorFn<T> = ValidatorFn<T>;
|
|
1070
|
+
type validation_ValidatorUsingKnownGoodVersionFn<In, Out = In> = ValidatorUsingKnownGoodVersionFn<In, Out>;
|
|
1071
|
+
declare const validation_any: typeof any;
|
|
1072
|
+
declare const validation_array: typeof array;
|
|
1073
|
+
declare const validation_arrayOf: typeof arrayOf;
|
|
1074
|
+
declare const validation_bigint: typeof bigint;
|
|
1075
|
+
declare const validation_boolean: typeof boolean;
|
|
1076
|
+
declare const validation_dict: typeof dict;
|
|
1077
|
+
declare const validation_httpUrl: typeof httpUrl;
|
|
1078
|
+
declare const validation_indexKey: typeof indexKey;
|
|
1079
|
+
declare const validation_integer: typeof integer;
|
|
1080
|
+
declare const validation_jsonDict: typeof jsonDict;
|
|
1081
|
+
declare const validation_jsonValue: typeof jsonValue;
|
|
1082
|
+
declare const validation_linkUrl: typeof linkUrl;
|
|
1083
|
+
declare const validation_literal: typeof literal;
|
|
1084
|
+
declare const validation_literalEnum: typeof literalEnum;
|
|
1085
|
+
declare const validation_model: typeof model;
|
|
1086
|
+
declare const validation_nonZeroFiniteNumber: typeof nonZeroFiniteNumber;
|
|
1087
|
+
declare const validation_nonZeroInteger: typeof nonZeroInteger;
|
|
1088
|
+
declare const validation_nonZeroNumber: typeof nonZeroNumber;
|
|
1089
|
+
declare const validation_nullable: typeof nullable;
|
|
1090
|
+
declare const validation_number: typeof number;
|
|
1091
|
+
declare const validation_numberUnion: typeof numberUnion;
|
|
1092
|
+
declare const validation_object: typeof object;
|
|
1093
|
+
declare const validation_optional: typeof optional;
|
|
1094
|
+
declare const validation_or: typeof or;
|
|
1095
|
+
declare const validation_positiveInteger: typeof positiveInteger;
|
|
1096
|
+
declare const validation_positiveNumber: typeof positiveNumber;
|
|
1097
|
+
declare const validation_setEnum: typeof setEnum;
|
|
1098
|
+
declare const validation_srcUrl: typeof srcUrl;
|
|
1099
|
+
declare const validation_string: typeof string;
|
|
1100
|
+
declare const validation_union: typeof union;
|
|
1101
|
+
declare const validation_unitInterval: typeof unitInterval;
|
|
1102
|
+
declare const validation_unknown: typeof unknown;
|
|
1103
|
+
declare const validation_unknownObject: typeof unknownObject;
|
|
1104
|
+
declare namespace validation {
|
|
1105
|
+
export { validation_ArrayOfValidator as ArrayOfValidator, validation_DictValidator as DictValidator, validation_ObjectValidator as ObjectValidator, type validation_TypeOf as TypeOf, validation_UnionValidator as UnionValidator, type validation_UnionValidatorConfig as UnionValidatorConfig, type validation_Validatable as Validatable, validation_ValidationError as ValidationError, validation_Validator as Validator, type validation_ValidatorFn as ValidatorFn, type validation_ValidatorUsingKnownGoodVersionFn as ValidatorUsingKnownGoodVersionFn, validation_any as any, validation_array as array, validation_arrayOf as arrayOf, validation_bigint as bigint, validation_boolean as boolean, validation_dict as dict, validation_httpUrl as httpUrl, validation_indexKey as indexKey, validation_integer as integer, validation_jsonDict as jsonDict, validation_jsonValue as jsonValue, validation_linkUrl as linkUrl, validation_literal as literal, validation_literalEnum as literalEnum, validation_model as model, validation_nonZeroFiniteNumber as nonZeroFiniteNumber, validation_nonZeroInteger as nonZeroInteger, validation_nonZeroNumber as nonZeroNumber, validation_nullable as nullable, validation_number as number, validation_numberUnion as numberUnion, validation_object as object, validation_optional as optional, validation_or as or, validation_positiveInteger as positiveInteger, validation_positiveNumber as positiveNumber, validation_setEnum as setEnum, validation_srcUrl as srcUrl, validation_string as string, validation_union as union, validation_unitInterval as unitInterval, validation_unknown as unknown, validation_unknownObject as unknownObject };
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
export { ArrayOfValidator, DictValidator, ObjectValidator, validation as T, UnionValidator, type UnionValidatorConfig, Validator };
|