TypeScript: EndsWith Utility Type
In TypeScript, we often need to create types that dynamically adapt based on the properties of other types. This challenge focuses on building a utility type that checks if a given tuple type ends with a specific type. This is useful for type-safe operations on arrays and tuples where you need to ensure a particular type exists at the end of a sequence.
Problem Description
Your task is to create a TypeScript utility type named EndsWith<T, U> where:
Tis a tuple type.Uis a single type.
The EndsWith<T, U> type should resolve to true if the last element of the tuple type T is assignable to the type U. Otherwise, it should resolve to false.
Key Requirements:
- The utility type must be named
EndsWith. - It must accept two type parameters:
T(the tuple) andU(the potential last element type). - It must return a boolean literal type (
trueorfalse). - The comparison should check if the type of the last element of
Tis assignable toU.
Expected Behavior:
- If
Tis an empty tuple[], it cannot end with any typeU, soEndsWith<[], U>should befalse. - If the last element of
Tis assignable toU, the type should resolve totrue. - If the last element of
Tis not assignable toU, the type should resolve tofalse.
Edge Cases:
- Empty tuple
[]. - Tuple with a single element.
- Comparing with
anyandunknown.
Examples
Example 1:
type MyTuple = [string, number, boolean];
type Result = EndsWith<MyTuple, boolean>;
// Expected Output: true
Explanation: The last element of MyTuple is boolean, which is assignable to boolean.
Example 2:
type MyTuple = [string, number, boolean];
type Result = EndsWith<MyTuple, number>;
// Expected Output: false
Explanation: The last element of MyTuple is boolean, which is not assignable to number.
Example 3:
type SingleElementTuple = [string];
type Result = EndsWith<SingleElementTuple, string>;
// Expected Output: true
Explanation: The last element of SingleElementTuple is string, which is assignable to string.
Example 4:
type EmptyTuple = [];
type Result = EndsWith<EmptyTuple, string>;
// Expected Output: false
Explanation: An empty tuple has no last element, so it cannot end with string.
Example 5:
type MixedTuple = [string, number];
type Result = EndsWith<MixedTuple, string | number>;
// Expected Output: true
Explanation: The last element of MixedTuple is number, which is assignable to string | number.
Example 6:
type AnyTuple = [string, any];
type Result = EndsWith<AnyTuple, string>;
// Expected Output: true
Explanation: The last element is any. string is assignable to any.
Example 7:
type UnknownTuple = [string, unknown];
type Result = EndsWith<UnknownTuple, string>;
// Expected Output: true
Explanation: The last element is unknown. string is assignable to unknown.
Constraints
- The utility type
EndsWithmust be implemented using only TypeScript's type-level features (conditional types, infer, etc.). - No runtime code execution is involved. The solution must be purely a compile-time type.
- Performance is not a primary concern for this exercise, but the solution should be reasonably efficient for typical tuple lengths.
Notes
To extract the last element of a tuple, you might consider using inference with rest parameters in conditional types. Remember how TypeScript handles tuple types and their elements. Consider how to handle the case of an empty tuple explicitly.