FindAll
Less than 1 minuteTC-Medium
FindAll
Problem
Given a pattern string P and a text string T, implement the type FindAll<T, P> that returns an array containing all the indices where P occurs in T.
type Matched = FindAll<'Collection | Mutation | Query', 'Collection'> // [0]
type Matched2 = FindAll<'TwoTwo', 'Two'> // [0, 3]
type Empty = FindAll<'', 'Two'> // []
type NotFound = FindAll<'Collection | Mutation | Query', 'Foo'> // []Solution
type FindAll<
T extends string,
P extends string,
Acc extends number[] = [],
Idx extends any[] = []
> =
P extends ''
? []
: T extends `${string}${infer Rest}`
? T extends `${P}${string}`
? FindAll<Rest, P, [...Acc, Idx['length']], [...Idx, unknown]>
: FindAll<Rest, P, Acc, [...Idx, unknown]>
: AccHow it works:
- Use
Idxas a counter (tuple length = current index). - At each position, check if the remaining string
Tstarts withPusingT extends \{string}``. - If yes, record
Idx['length']inAccand advance one character. - Otherwise just advance one character.
- Return
Accwhen the string is exhausted.
Key Takeaways
- Tracking position with a tuple counter (
Idx['length']) is the standard way to get numeric indices in TS type recursion. - Checking
T extends \{string}`` tests whether the current suffix starts with the pattern. - Advancing by one character at a time (
T extends \{infer Rest}``) allows overlapping matches.
