Yuzhe's Blog

yuzhes

Combination

Combination

Problem Link

Problem

Given an array of strings, do Permutation & Combination. It’s also useful for the Vuex binding helpers.

type Keys = Combination<['foo', 'bar', 'baz']>
// 'foo' | 'bar' | 'baz' | 'foo bar' | 'foo baz' | 'bar baz' | 'foo bar baz' ...

Solution

Approach: Union Distribution with Exclusion

Convert the array to a union, then for each element, combine it with all sub-combinations of the remaining elements.

type Combination<T extends string[], U extends string = T[number]> =
  U extends string
    ? U | `${U} ${Combination<[], Exclude<U, U>> }` | `${U} ${string & Exclude<T[number], U>}`
    : never

A cleaner version:

type Combination<
  T extends string[],
  All extends string = T[number],
  U extends string = All
> = U extends All
  ? U | `${U} ${Combination<[], Exclude<All, U>>}`
  : never

How it works:

  1. T[number] converts the tuple to a string union All.
  2. Distribute over each member U of All.
  3. For each U, produce U alone or U followed by space and a combination of the remaining items.
  4. Exclude<All, U> removes the current item to avoid repeats.

Key Takeaways