Home > Software design >  Typescript - Filter a generic array type by element type
Typescript - Filter a generic array type by element type

Time:08-26

I have an array of values:

const array = ['b', 'a', 'b', 'a', 'c'] as const;

So the type is:

const array: readonly ["b", "a", "b", "a", "c"]

Now I want to create a type that filters the array, and returns a type of array with only the filtered elements. I've created a FilterArray type, that does the trick, however, the indexes on the array are taken from the first array and not restarted.

type FilterArray<T extends readonly any[], V> = {
    [I in keyof T as [Extract<T[I], V>] extends [never] ? never : I]: T[I];
}

If I filter now on typeof array, I get these results: filter results filteredArray[3] is also of type 'a', which is correct.

Is it possible to restart the index from 0? Or should I take another approach?

CodePudding user response:

The problem here is that you are using a mapped type with key remapping. Because of the key remapping, the resulting type of FilterArray is not a tuple but an object type with the two properties 1 and 3.

To get a tuple type as the result, you need a recursive type.

type FilterArray<T extends readonly any[], V> = 
  T extends readonly [infer L, ...infer R]
    ? L extends V
      ? [L, ...FilterArray<R, V>]
      : [...FilterArray<R, V>]
    : []

This type iterates through the array and adds matching elements to the output.

The resulting type would now look like this:

const filteredArray = {} as FilterArray<typeof array, "a">
//    ^? ["a", "a"]

Playground

  • Related