34007 · CompareArrayLength
34007 · CompareArrayLength
Problem
Implement CompareArrayLength<T, U> that compares the lengths of two arrays and returns:
1ifTis longer thanU-1ifTis shorter thanU0if they are the same length
type cases = [
Expect<Equal<CompareArrayLength<[1, 2, 3, 4], [5, 6]>, 1>>,
Expect<Equal<CompareArrayLength<[1, 2], [3, 4, 5, 6]>, -1>>,
Expect<Equal<CompareArrayLength<[], []>, 0>>,
Expect<Equal<CompareArrayLength<[1, 2, 3], [4, 5, 6]>, 0>>,
]Solution
type CompareArrayLength<T extends any[], U extends any[]> =
T['length'] extends U['length']
? 0
: T extends [any, ...infer TR]
? U extends [any, ...infer UR]
? CompareArrayLength<TR, UR>
: 1
: -1Explanation
The solution uses recursive tail-peeling to compare arrays element by element until one runs out.
Step by step:
T['length'] extends U['length']— if both lengths are already equal (TypeScript can check literal number equality here), return0immediately. This handles same-length arrays like[1,2,3]vs[4,5,6].If lengths differ, we recurse by peeling one element off each:
T extends [any, ...infer TR]— try to peel the head ofT; if it fails,Tis emptyU extends [any, ...infer UR]— try to peel the head ofU; if it fails,Uis empty
If both can be peeled, recurse with
CompareArrayLength<TR, UR>— effectively counting down simultaneously.If
Tcan be peeled butUcannot —Tstill has elements whileUis exhausted →Tis longer → return1.If
Tcannot be peeled (but the length check failed, meaningUis longer) → return-1.
Why check T['length'] extends U['length'] first?
Without this check, the recursion would always peel until one is empty. The early exit makes the logic cleaner and avoids unnecessary recursion for same-length tuples.
Key Concepts
- Tuple length indexing —
T['length']gives the literal number type for tuple lengths - Variadic tuple spreading —
[any, ...infer Rest]deconstructs a tuple, extracting head and tail - Recursive conditional types — using self-referential type aliases to simulate loops
