Type-Level Binary Search in TypeScript
This challenge asks you to implement a binary search algorithm operating entirely at the type level in TypeScript. Type-level programming allows us to perform computations and manipulations using types as if they were values, enabling powerful compile-time checks and optimizations. This exercise will test your understanding of conditional types, mapped types, and recursive type manipulations.
Problem Description
You need to create a type BinarySearch<T extends number[], Target extends number, Start extends number = 0, End extends number = 0> that performs a binary search on a sorted number array T to find the index of a Target number. The Start and End parameters represent the search boundaries, defaulting to 0 and the length of the array respectively. The type should return the index of the Target if found, otherwise it should return -1.
Key Requirements:
- The input array
Tmust be sorted in ascending order. - The
StartandEndparameters should define the search range within the array. - The algorithm should recursively divide the search space in half until the
Targetis found or the search space is exhausted. - The return type should be a number representing the index of the
Targetin the array, or-1if theTargetis not found. - The solution must be purely type-level; no runtime code is allowed.
Expected Behavior:
- If the
Targetexists in the array, the type should resolve to the index of theTarget. - If the
Targetdoes not exist in the array, the type should resolve to-1. - The type should handle edge cases such as empty arrays,
Targetsmaller than the smallest element, andTargetlarger than the largest element.
Edge Cases to Consider:
- Empty array
T: Should return-1. Targetsmaller than the smallest element inT: Should return-1.Targetlarger than the largest element inT: Should return-1.Targetis the first or last element ofT.StartandEndare out of bounds (though the default values should handle this).
Examples
Example 1:
Input: [1, 2, 3, 4, 5], 3
Output: 2
Explanation: The target 3 is found at index 2 in the array [1, 2, 3, 4, 5].
Example 2:
Input: [1, 2, 3, 4, 5], 6
Output: -1
Explanation: The target 6 is not found in the array [1, 2, 3, 4, 5].
Example 3:
Input: [2, 5, 7, 8, 11, 12], 13, 0, 5
Output: -1
Explanation: The target 13 is not found within the specified range [0, 5] of the array [2, 5, 7, 8, 11, 12].
Example 4:
Input: [1, 2, 3], 1, 0, 0
Output: 0
Explanation: The target 1 is found at index 0 in the array [1, 2, 3] within the range [0, 0].
Constraints
Tmust be an array of numbers (number[]).Targetmust be a number.StartandEndmust be numbers.- The array
Tis guaranteed to be sorted in ascending order. - The solution should be as efficient as possible in terms of type complexity (avoiding excessively deep recursion).
Notes
- Consider using conditional types to check if the
Targetfalls within the current search range. - You'll likely need to use mapped types to extract elements from the array based on their index.
- Recursion is essential for implementing the binary search logic at the type level.
- Think about how to handle the base cases (target found, search space exhausted).
- The
Exclude<number, -1>type can be useful for ensuring the index is a valid positive number. - The
[key: number]index signature is crucial for accessing array elements by index within types.