Hone logo
Hone
Problems

Contract Types System in TypeScript

This challenge asks you to implement a simplified contract types system in TypeScript. Contract types are a powerful tool for defining the expected shape of data passed between functions or components, enhancing type safety and improving code maintainability. By creating a basic system, you'll gain a deeper understanding of TypeScript's type system and how it can be leveraged for more robust code.

Problem Description

You are tasked with creating a Contract class and a helper function validate that enforces contract types. The Contract class should allow you to define a set of key-value pairs, where each key represents a property name and each value represents the expected type for that property. The validate function should take an object and a Contract instance as input and return true if the object conforms to the contract (i.e., all required properties exist and have the correct types), and false otherwise.

Key Requirements:

  • Contract Class:
    • Should accept a type definition object (e.g., { name: string, age: number }) during instantiation.
    • Should store the type definition internally.
  • validate Function:
    • Should take an object and a Contract instance as arguments.
    • Should iterate through the contract's type definition.
    • For each property in the contract:
      • Check if the property exists in the input object.
      • If the property exists, check if its type matches the type defined in the contract using TypeScript's type guards.
    • Should return true only if all properties in the contract are present and of the correct type. Otherwise, return false.
  • Type Guards: Utilize TypeScript's type guards (e.g., typeof, Array.isArray) to perform type checking.

Expected Behavior:

The validate function should accurately determine whether an object conforms to a given contract. It should handle cases where properties are missing or have incorrect types.

Edge Cases to Consider:

  • Missing Properties: The object should fail validation if a property defined in the contract is missing.
  • Incorrect Types: The object should fail validation if a property has a type that does not match the contract's definition.
  • Null/Undefined Values: Consider how you want to handle null or undefined values. For this challenge, treat them as type mismatches unless the contract explicitly allows them (e.g., age?: number).
  • Optional Properties: The contract should support optional properties (e.g., age?: number). If a property is optional and missing, validation should still pass.
  • Arrays and Objects: The contract should be able to handle arrays and nested objects as types.

Examples

Example 1:

Input:
contract = new Contract({ name: string, age: number });
object = { name: "Alice", age: 30 };

Output: true
Explanation: The object has both 'name' (string) and 'age' (number) properties, matching the contract.

Example 2:

Input:
contract = new Contract({ name: string, age: number });
object = { name: "Bob" };

Output: false
Explanation: The object is missing the 'age' property, which is required by the contract.

Example 3:

Input:
contract = new Contract({ name: string, age?: number });
object = { name: "Charlie" };

Output: true
Explanation: The object has the required 'name' property (string) and the optional 'age' property is missing, which is acceptable.

Example 4:

Input:
contract = new Contract({ data: Array<string> });
object = { data: ["a", "b", "c"] };

Output: true
Explanation: The object has a 'data' property which is an array of strings, matching the contract.

Constraints

  • The Contract class should be implemented using a class.
  • The validate function should be a standalone function.
  • The contract type definitions should be plain JavaScript objects.
  • The solution should be written in TypeScript.
  • Performance is not a primary concern for this challenge; focus on correctness and clarity.

Notes

  • Consider using TypeScript's conditional types to improve type safety within the validate function.
  • Think about how to handle more complex type definitions (e.g., unions, intersections) if you want to extend the system further.
  • This is a simplified contract system. Real-world contract systems often involve more sophisticated features like custom validation rules and error reporting.
  • Focus on the core functionality of validating object properties against a defined type contract.
Loading editor...
typescript