Hone logo
Hone
Problems

Maintaining Backward Compatibility During TypeScript Refactoring

As TypeScript projects evolve, refactoring code to leverage newer language features or improve architecture is inevitable. However, these changes can break existing code that relies on the older API. This challenge focuses on implementing a mechanism to provide backward compatibility, allowing older code to continue functioning while newer code utilizes the refactored version.

Problem Description

You are tasked with creating a compatibility layer for a TypeScript module that has undergone a significant API change. The original module, OldModule, exposes a function oldFunction that takes a string and returns a number. The refactored module, NewModule, replaces oldFunction with newFunction, which now takes a number and returns a string. Your goal is to create a CompatibilityModule that acts as an intermediary. This module should:

  1. Accept either the old or new function signature. If the input to CompatibilityModule.compatibleFunction is a string, it should call NewModule.newFunction with the string converted to a number. If the input is a number, it should call NewModule.newFunction directly.
  2. Return the appropriate type. If NewModule.newFunction returns a string, CompatibilityModule.compatibleFunction should return that string.
  3. Handle potential errors gracefully. If the input to CompatibilityModule.compatibleFunction is not a string or a number, it should throw a TypeError with a descriptive message.
  4. Maintain type safety. The TypeScript compiler should be able to infer the correct types for the input and output of CompatibilityModule.compatibleFunction.

Examples

Example 1:

Input: CompatibilityModule.compatibleFunction("123")
Output: "123"
Explanation: The input string "123" is converted to the number 123, passed to NewModule.newFunction, which returns "123".

Example 2:

Input: CompatibilityModule.compatibleFunction(456)
Output: "456"
Explanation: The number 456 is passed directly to NewModule.newFunction, which returns "456".

Example 3:

Input: CompatibilityModule.compatibleFunction(true)
Output: TypeError: Input must be a string or a number.
Explanation: The input `true` is neither a string nor a number, so a TypeError is thrown.

Constraints

  • The NewModule is assumed to be already implemented and cannot be modified.
  • The OldModule is not needed for this challenge; only the compatibility layer needs to be implemented.
  • The conversion from string to number should use Number().
  • The CompatibilityModule should be implemented in TypeScript.
  • The solution should be well-typed and avoid unnecessary type assertions.

Notes

Consider using TypeScript's type guards to determine the type of the input argument. Think about how to handle potential errors during the string-to-number conversion (e.g., if the string cannot be parsed as a number). The goal is to provide a seamless transition for existing code while allowing new code to utilize the improved NewModule API. Focus on creating a robust and type-safe compatibility layer.

// NewModule (Assume this is already implemented and cannot be changed)
const newFunction = (num: number): string => {
  return num.toString();
};

// OldModule (Not needed for the solution, just for context)
// const oldFunction = (str: string): number => {
//   return parseInt(str, 10);
// };

Loading editor...
typescript