Typescript has revolutionized type validation
in development, functioning primarily as a sophisticated linter to ensure type safety during this phase. However, TypeScript’s capabilities don’t extend to runtime. To bridge this gap, runtime validators like yup, io-ts, and zod come into play. This guide delves into leveraging these tools for a comprehensive validation strategy.
Advanced Type Definition for a Todo Item
type TodoItem = {
id: string;
title: string;
done: boolean;
createdAt: Date;
updatedAt: Date;
};
Creating a Robust Runtime Schema for the Todo Item with Zod
import * as z from "zod";
const TodoItemValidator = z.object({
id: z.string(),
title: z.string(),
done: z.boolean(),
createdAt: z.date(),
updatedAt: z.date(),
});
Here, Zod’s schema mirrors the TypeScript type, ensuring congruence between compile-time and runtime validations.
Comprehensive Strategy for Validation
1. Define a Detailed Entity Schema
import * as z from "zod";
const TodoItemValidator = z.object({
id: z.string(),
title: z.string(),
done: z.boolean(),
createdAt: z.date(),
updatedAt: z.date(),
});
2. Implement Granular Request and Response Validations
For backend APIs, use specific validators for request and response payloads.
// Define specific attributes for the create API request
const TodoItemCreateRequestValidator = TodoItemValidator.pick({
title: true,
done: true,
});
// Validator for the response when fetching a specific Todo item
const TodoItemGetByIdResponseValidator = TodoItemValidator;
3. Generate Sophisticated Types from Zod Validations
type TodoItemType = z.infer<typeof TodoItemValidator>;
type TodoItemCreateRequestType = z.infer<typeof TodoItemCreateRequestValidator>;
type TodoItemCreateResponseType = z.infer<
typeof TodoItemGetByIdResponseValidator
>;
4. Integrate the Types in Frontend Development
import axios from "axios";
let data: TodoItemCreateRequestType = {
title: "work work work",
done: false,
};
axios
.post<TodoItemCreateResponseType>("http://localhost:8080/todoitem", data)
.then(response => {
console.log(response.data);
});
5. Apply Validators in Form Submissions and Backend API
For frontend form submissions and backend API interactions, employ the validators to ensure data integrity.
// Validate incoming request payload
const validateRequestPayload =
TodoItemCreateRequestValidator.safeParse(payload);
// Validate API response data
const validateResponse = TodoItemGetByIdResponseValidator.safeParse(response);
// Use `validate.success` for boolean validation result
In-Depth Conclusion
We began with the creation of a comprehensive entity validator, a critical step in our type safety journey. Building upon this, we specified request and response validators, each with their distinct types derived from Zod schemas. This approach not only guarantees consistency between TypeScript’s compile-time checks and Zod’s runtime validation but also ensures a robust, error-resistant application. By meticulously implementing these strategies, developers can achieve unparalleled levels of type safety and data integrity in both frontend and backend environments.