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:
- Accept either the old or new function signature. If the input to
CompatibilityModule.compatibleFunctionis a string, it should callNewModule.newFunctionwith the string converted to a number. If the input is a number, it should callNewModule.newFunctiondirectly. - Return the appropriate type. If
NewModule.newFunctionreturns a string,CompatibilityModule.compatibleFunctionshould return that string. - Handle potential errors gracefully. If the input to
CompatibilityModule.compatibleFunctionis not a string or a number, it should throw aTypeErrorwith a descriptive message. - 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
NewModuleis assumed to be already implemented and cannot be modified. - The
OldModuleis not needed for this challenge; only the compatibility layer needs to be implemented. - The conversion from string to number should use
Number(). - The
CompatibilityModuleshould 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);
// };