Hone logo
Hone
Problems

Type Versioning in TypeScript

Implementing type versioning allows you to manage changes to your types over time, ensuring compatibility and preventing breaking changes when updating dependencies or refactoring code. This challenge focuses on creating a system that allows you to specify and enforce version constraints on your TypeScript types, similar to how package versioning works in npm. This is particularly useful in large projects or when collaborating with others.

Problem Description

You need to create a system for versioning TypeScript types. This system should allow you to define a type with a specific version and then check if a given type satisfies a version constraint. The core of the solution is a Version type and a TypeWithVersion type, along with a function satisfiesVersion that determines if a TypeWithVersion satisfies a given version constraint.

What needs to be achieved:

  • Define a Version type that represents a semantic version (major.minor.patch). It should be a tuple of three numbers: [major: number, minor: number, patch: number].
  • Define a TypeWithVersion type that combines a TypeScript type and a Version. It should look like: { type: any; version: Version }.
  • Create a function satisfiesVersion(typeWithVersion: TypeWithVersion, versionConstraint: Version): boolean. This function should take a TypeWithVersion and a Version constraint as input and return true if the TypeWithVersion's version satisfies the constraint, and false otherwise.

Key requirements:

  • The satisfiesVersion function should support the following version constraint logic:
    • Exact match: [1, 2, 3] matches [1, 2, 3]
    • Greater than or equal to: [1, 2, 3] matches [1, 2, 2]
    • Less than or equal to: [1, 2, 3] matches [1, 2, 4]
    • Major version match: [1, 2, 3] matches [1, 0, 0] (matches if major versions are the same)
    • Any version: [0, 0, 0] (or any version with all zeros) should match any version. This acts as a wildcard.

Expected behavior:

The satisfiesVersion function should accurately determine if a TypeWithVersion's version meets the specified constraint. The constraint logic should be implemented correctly, covering all the specified cases.

Edge cases to consider:

  • Invalid version numbers (e.g., negative numbers). While not strictly required to handle these, consider how your solution might behave.
  • Zero values for major, minor, and patch versions.
  • Constraints that are not valid versions (e.g., [1, "a", 3]). The solution should gracefully handle these, ideally by returning false.

Examples

Example 1:

Input: typeWithVersion = { type: string, version: [1, 2, 3] }, versionConstraint = [1, 2, 3]
Output: true
Explanation: Exact version match.

Example 2:

Input: typeWithVersion = { type: number, version: [1, 2, 4] }, versionConstraint = [1, 2, 3]
Output: true
Explanation: Version of typeWithVersion is greater than or equal to the constraint.

Example 3:

Input: typeWithVersion = { type: boolean, version: [1, 3, 0] }, versionConstraint = [1, 2, 3]
Output: false
Explanation: Version of typeWithVersion is not greater than or equal to the constraint.

Example 4:

Input: typeWithVersion = { type: any, version: [2, 0, 0] }, versionConstraint = [1, 0, 0]
Output: true
Explanation: Major version match.

Example 5:

Input: typeWithVersion = { type: object, version: [1, 2, 3] }, versionConstraint = [0, 0, 0]
Output: true
Explanation: Constraint is a wildcard (matches any version).

Constraints

  • The Version type must be a tuple of three numbers.
  • The satisfiesVersion function must handle all the specified constraint types (exact match, greater than or equal to, less than or equal to, major version match, and any version).
  • The solution should be reasonably efficient. While performance is not a primary concern, avoid unnecessary complexity.

Notes

  • Consider using helper functions to make the satisfiesVersion function more readable and maintainable.
  • Think about how you can generalize the constraint logic to support more complex versioning schemes in the future.
  • The type property of TypeWithVersion is not used in the version comparison logic; it's included to represent a real-world scenario where you might have a type associated with a version.
Loading editor...
typescript