Implementing runtime data validation in TypeScript involves using either custom validation functions or a library that can handle validations based on your data schema. TypeScript itself does not enforce runtime type safety, as it only provides static type checking. Here are some approaches you can take:
For each field, you can write functions that check whether the data meets the required criteria, such as string length, numeric ranges, or regex patterns.
Example Implementation:
type DAOSchema = {
name: string;
address: string;
coolDownPeriod: number;
};
function validateName(name: string): boolean {
return name.length >= 3 && name.length <= 50;
}
function validateAddress(address: string): boolean {
const pattern = /^(([a-z\\\\d]+[-_])*[a-z\\\\d]+\\\\.)*([a-z\\\\d]+[-_])*[a-z\\\\d]+$/;
return pattern.test(address);
}
function validateCoolDownPeriod(period: number): boolean {
return period >= 0 && period <= 31536000;
}
function validateDAO(dao: DAOSchema): boolean {
return validateName(dao.name) &&
validateAddress(dao.address) &&
validateCoolDownPeriod(dao.coolDownPeriod);
}
const dao = {
name: "Example DAO",
address: "example.dao",
coolDownPeriod: 86400,
};
if (validateDAO(dao)) {
console.log("DAO is valid!");
} else {
console.log("DAO validation failed.");
}
There are libraries like Joi or Yup that can simplify the validation process by allowing you to define a schema with validation rules.
Example with Joi:
import Joi from 'joi';
const daoSchema = Joi.object({
name: Joi.string().min(3).max(50).required(),
address: Joi.string().pattern(new RegExp('...')).required(),
coolDownPeriod: Joi.number().min(0).max(31536000).required(),
});
const { error } = daoSchema.validate({
name: "Example DAO",
address: "example.dao",
coolDownPeriod: 86400,
});
if (error) {
console.error("Validation failed:", error.details);
} else {
console.log("Validation successful!");
}
Example with Yup:
import * as Yup from 'yup';
const daoSchema = Yup.object().shape({
name: Yup.string().min(3).max(50).required(),
address: Yup.string().matches(/^(([a-z\\\\d]+[-_])*[a-z\\\\d]+\\\\.)*([a-z\\\\d]+[-_])*[a-z\\\\d]+$/).required(),
coolDownPeriod: Yup.number().min(0).max(31536000).required(),
});
daoSchema.validate({
name: "Example DAO",
address: "example.dao",
coolDownPeriod: 86400,
}).then(() => {
console.log("Validation successful!");
}).catch(error => {
console.error("Validation failed:", error.errors);
});
If your TypeScript application is server-side or uses APIs, you can integrate these validation checks into your middleware (e.g., with Express.js) to validate incoming data before processing it.
Choosing between custom validation functions and third-party libraries depends on your project's complexity and specific needs. Libraries can offer a more robust, maintainable, and scalable solution for larger projects or where validations are complex and frequently updated.