Hone logo
Hone
Problems

Robust Data Validation with TypeScript Schemas

Data validation is crucial for building reliable applications. This challenge focuses on implementing a flexible schema validation system in TypeScript using type definitions to enforce data structure and type constraints. You'll define reusable schema types and functions to validate data against these schemas, ensuring data integrity and preventing unexpected errors.

Problem Description

You are tasked with creating a TypeScript library for validating data against predefined schemas. The schema should be defined using TypeScript types and should support various validation rules, including:

  • Type Checking: Ensuring that a field has the correct data type (string, number, boolean, array, object, etc.).
  • Required Fields: Verifying that certain fields are present in the data.
  • String Length: Validating that string fields have a minimum and/or maximum length.
  • Number Range: Validating that number fields fall within a specified range (minimum and/or maximum).
  • Array Element Type: Validating that all elements in an array have a specific type.
  • Object Shape: Validating that an object has a specific structure (keys and their types).

Your solution should include:

  1. Schema Definition Types: Define TypeScript types to represent the schema itself. This should be flexible enough to accommodate different validation rules.
  2. Validation Function: Create a function validate that takes data and a schema as input and returns either true if the data is valid according to the schema, or an array of error messages if the data is invalid.
  3. Error Messages: Error messages should be descriptive and indicate which field failed validation and why.

Examples

Example 1:

Input:
data = { name: "John Doe", age: 30, city: "New York" };
schema = {
  name: { type: "string", required: true },
  age: { type: "number", required: true, min: 0, max: 120 },
  city: { type: "string", required: false, min: 3, max: 50 }
};

Output:
true
Explanation: The data matches the schema. All required fields are present, types are correct, and string lengths are within the allowed range.

Example 2:

Input:
data = { name: "Jane", age: "thirty", city: "London" };
schema = {
  name: { type: "string", required: true },
  age: { type: "number", required: true, min: 0, max: 120 },
  city: { type: "string", required: false, min: 3, max: 50 }
};

Output:
[
  "age: Invalid type. Expected 'number', got 'string'.",
  "city: Invalid length. Must be between 3 and 50 characters, but got 6."
]
Explanation: The data is invalid because the 'age' field has the wrong type and the 'city' field's length is outside the allowed range.

Example 3:

Input:
data = { name: "", age: 25 };
schema = {
  name: { type: "string", required: true, min: 2 },
  age: { type: "number", required: true }
};

Output:
["name: Invalid length. Must be at least 2 characters, but got 0."]
Explanation: The 'name' field is required and has a minimum length of 2, but it's an empty string.

Constraints

  • The validate function should handle various data types: string, number, boolean, array, and object.
  • The schema should be extensible to support additional validation rules in the future.
  • Error messages should be clear and informative, indicating the field name, the validation rule that failed, and the reason for the failure.
  • The solution should be well-structured and maintainable.
  • Performance should be reasonable for typical data validation scenarios. Avoid unnecessary iterations or complex logic.

Notes

  • Consider using TypeScript's conditional types and discriminated unions to create a flexible schema definition.
  • Think about how to handle nested objects and arrays within the schema.
  • You don't need to implement every possible validation rule, but the solution should demonstrate a solid understanding of schema validation principles.
  • Focus on creating a reusable and extensible validation library. The goal is not just to validate a specific dataset, but to create a tool that can be used to validate various data structures.
  • The type property in the schema should be a string representing the expected data type (e.g., "string", "number", "boolean", "array", "object").
  • For arrays, the schema should include a elementType property to specify the type of elements in the array.
Loading editor...
typescript