ArrayOfValidator
Table of contents
Extends Validator<T[]>.
Validator for arrays where each element is validated using the provided item validator. Extends the base Validator class with array-specific validation methods.
class ArrayOfValidator<T> extends Validator<T[]> {}Example
const stringArray = new ArrayOfValidator(T.string);
const numbers = stringArray.validate(["a", "b", "c"]); // Returns string[]
const userArray = T.arrayOf(T.object({ name: T.string, age: T.number }));Constructor
Creates a new ArrayOfValidator.
itemValidator - Validator used to validate each array element
Parameters
| Name | Description |
|---|---|
| |
Properties
itemValidator
readonly itemValidator: Validatable<T>;validateUsingKnownGoodVersionFn
readonly validateUsingKnownGoodVersionFn?:
| undefined
| ValidatorUsingKnownGoodVersionFn<T, T>;validationFn
readonly validationFn: ValidatorFn<T>;Methods
check( )
Adds an additional validation check without changing the resulting value type. Can be called with just a check function, or with a name for better error messages.
check(name: string, checkFn: (value: T) => void): Validator<T>;Example
import { T, ValidationError } from "@tldraw/validate";
// Basic check without name
const evenNumber = T.number.check((value) => {
if (value % 2 !== 0) {
throw new ValidationError("Expected even number");
}
});
// Named checks for better error messages in complex validators
const shapePositionValidator = T.object({
x: T.number.check("finite", (value) => {
if (!Number.isFinite(value)) {
throw new ValidationError("Position must be finite");
}
}),
y: T.number.check("within-bounds", (value) => {
if (value < -10000 || value > 10000) {
throw new ValidationError(
"Position must be within bounds (-10000 to 10000)",
);
}
}),
});
// Error will be: "At x (check finite): Position must be finite"Parameters
| Name | Description |
|---|---|
| Name for the check (used in error messages) |
| Function that validates the value (should throw on invalid input) |
Returns
Validator<T>;A new validator with the additional check
isValid( )
Type guard that checks if a value is valid without throwing an error.
isValid(value: unknown): value is T;Example
import { T } from "@tldraw/validate";
function processUserInput(input: unknown) {
if (T.string.isValid(input)) {
// input is now typed as string within this block
return input.toUpperCase();
}
if (T.number.isValid(input)) {
// input is now typed as number within this block
return input.toFixed(2);
}
throw new Error("Expected string or number");
}Parameters
| Name | Description |
|---|---|
| The value to check |
Returns
value is T;True if the value is valid, false otherwise
lengthGreaterThan1( )
Returns a new validator that ensures the array has more than one element.
lengthGreaterThan1(): Validator<T[]>;Example
const multipleItems = T.arrayOf(T.string).lengthGreaterThan1();
multipleItems.validate(["a", "b"]); // Valid
multipleItems.validate(["a"]); // Throws ValidationErrornonEmpty( )
Returns a new validator that ensures the array is not empty.
nonEmpty(): Validator<T[]>;Example
const nonEmptyStrings = T.arrayOf(T.string).nonEmpty();
nonEmptyStrings.validate(["hello"]); // Valid
nonEmptyStrings.validate([]); // Throws ValidationErrornullable( )
Returns a new validator that also accepts null values.
nullable(): Validator<null | T>;Example
import { T } from "@tldraw/validate";
const assetValidator = T.object({
id: T.string,
name: T.string,
src: T.srcUrl.nullable(), // Can be null if not loaded yet
mimeType: T.string.nullable(),
});
const asset = assetValidator.validate({
id: "image-123",
name: "photo.jpg",
src: null, // Valid - asset not loaded yet
mimeType: "image/jpeg",
});optional( )
Returns a new validator that also accepts undefined values.
optional(): Validator<T | undefined>;Example
import { T } from "@tldraw/validate";
const shapeConfigValidator = T.object({
type: T.literal("rectangle"),
x: T.number,
y: T.number,
label: T.string.optional(), // Optional property
metadata: T.object({ created: T.string }).optional(),
});
// Both of these are valid:
const shape1 = shapeConfigValidator.validate({ type: "rectangle", x: 0, y: 0 });
const shape2 = shapeConfigValidator.validate({
type: "rectangle",
x: 0,
y: 0,
label: "My Shape",
});refine( )
Creates a new validator by refining this validator with additional logic that can transform the validated value to a new type.
refine<U>(otherValidationFn: (value: T) => U): Validator<U>;Example
import { T, ValidationError } from "@tldraw/validate";
// Transform string to ensure it starts with a prefix
const prefixedIdValidator = T.string.refine((id) => {
return id.startsWith("shape:") ? id : `shape:${id}`;
});
const id1 = prefixedIdValidator.validate("rectangle-123"); // Returns "shape:rectangle-123"
const id2 = prefixedIdValidator.validate("shape:circle-456"); // Returns "shape:circle-456"
// Parse and validate JSON strings
const jsonValidator = T.string.refine((str) => {
try {
return JSON.parse(str);
} catch {
throw new ValidationError("Invalid JSON string");
}
});Parameters
| Name | Description |
|---|---|
| Function that transforms/validates the value to type U |
Returns
Validator<U>;A new validator that validates to type U
validate( )
Validates an unknown value and returns it with the correct type. The returned value is guaranteed to be referentially equal to the passed value.
validate(value: unknown): T;Example
import { T } from "@tldraw/validate";
const name = T.string.validate("Alice"); // Returns "Alice" as string
const title = T.string.validate(""); // Returns "" (empty strings are valid)
// These will throw ValidationError:
T.string.validate(123); // Expected string, got a number
T.string.validate(null); // Expected string, got null
T.string.validate(undefined); // Expected string, got undefinedParameters
| Name | Description |
|---|---|
| The unknown value to validate |
Returns
T;The validated value with type T
validateUsingKnownGoodVersion( )
Performance-optimized validation using a previously validated value. If the new value is referentially equal to the known good value, returns the known good value immediately.
validateUsingKnownGoodVersion(knownGoodValue: T, newValue: unknown): T;Example
import { T } from "@tldraw/validate";
const userValidator = T.object({
name: T.string,
settings: T.object({ theme: T.literalEnum("light", "dark") }),
});
const user = userValidator.validate({
name: "Alice",
settings: { theme: "light" },
});
// Later, with partially changed data:
const newData = { name: "Alice", settings: { theme: "dark" } };
const updated = userValidator.validateUsingKnownGoodVersion(user, newData);
// Only validates the changed 'theme' field for better performanceParameters
| Name | Description |
|---|---|
| A previously validated value |
| The new value to validate |
Returns
T;The validated value, potentially reusing the known good value