Yuzhe's Blog

yuzhes

Fill

Fill

Problem Link

Problem

Fill, a common JavaScript function, now let us implement it with types. Fill<T, N, Start?, End?> accepts four types of parameters, of which T and N are required parameters, and Start and End are optional parameters whose default values are 0 and the length of T.

type exp = Fill<[1, 2, 3], 0>     // [0, 0, 0]
type exp2 = Fill<[1, 2, 3], 0, 1> // [1, 0, 0]  (fill from index 1)

Solution

Approach: Index Counter with Tuple Accumulator

Track the current index with a tuple Count. Replace elements when Count['length'] is in [Start, End).

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  Count extends unknown[] = [],
  Flag extends boolean = GreaterThan<Count['length'], Start> extends true ? true : Count['length'] extends Start ? true : false
> = T extends [infer Head, ...infer Tail]
  ? Flag extends true
    ? Count['length'] extends End
      ? T  // reached End, stop filling
      : [N, ...Fill<Tail, N, Start, End, [...Count, unknown], true>]
    : [Head, ...Fill<Tail, N, Start, End, [...Count, unknown]>]
  : []

A cleaner alternative avoids the complex default:

type GreaterThan<T extends number, U extends number, Count extends unknown[] = []> =
  T extends U ? false :
  Count['length'] extends T ? false :
  Count['length'] extends U ? true :
  GreaterThan<T, U, [...Count, unknown]>

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T['length'],
  Count extends unknown[] = []
> = T extends [infer Head, ...infer Tail]
  ? GreaterThan<Count['length'], Start> extends true
    ? Count['length'] extends End
      ? [Head, ...Fill<Tail, N, Start, End, [...Count, unknown]>]
      : [N, ...Fill<Tail, N, Start, End, [...Count, unknown]>]
    : Count['length'] extends Start
      ? Count['length'] extends End
        ? [Head, ...Fill<Tail, N, Start, End, [...Count, unknown]>]
        : [N, ...Fill<Tail, N, Start, End, [...Count, unknown]>]
      : [Head, ...Fill<Tail, N, Start, End, [...Count, unknown]>]
  : []

How it works:

  1. Walk through T element by element, tracking index via Count['length'].
  2. Fill with N when index is in [Start, End).
  3. Once index reaches End, stop filling and keep original values.

Key Takeaways