#5360Medium

Unique

Implement the type version of Lodash.uniq, Unique<T> takes an Array T, returns the Array T without repeated values. Learn array type operations in this medium-level challenge on TypeScriptPro.

In this medium-level challenge, you'll implement a type-level version of Lodash's uniq function that removes duplicate values from a tuple type, preserving the order of first occurrences.

Challenge Instructions: Unique

Medium

Implement the type version of Lodash.uniq, Unique<T> takes an Array T, returns the Array T without repeated values.

type Res = Unique<[1, 1, 2, 2, 3, 3]>; // expected to be [1, 2, 3]
type Res1 = Unique<[1, 2, 3, 4, 4, 5, 6, 7]>; // expected to be [1, 2, 3, 4, 5, 6, 7]
type Res2 = Unique<[1, "a", 2, "b", 2, "a"]>; // expected to be [1, "a", 2, "b"]
type Res3 = Unique<[string, number, 1, "a", 1, string, 2, "b", 2, number]>; // expected to be [string, number, 1, "a", 2, "b"]
type Res4 = Unique<[unknown, unknown, any, any, never, never]>; // expected to be [unknown, any, never]

Change the following code to make the test cases pass (no type check errors).

ChallengeSolution
type cases = [
  Expect<Equal<Unique<[1, 1, 2, 2, 3, 3]>, [1, 2, 3]>>,
  Expect<Equal<Unique<[1, 2, 3, 4, 4, 5, 6, 7]>, [1, 2, 3, 4, 5, 6, 7]>>,
  Expect<Equal<Unique<[1, 'a', 2, 'b', 2, 'a']>, [1, 'a', 2, 'b']>>,
  Expect<
    Equal<
      Unique<[string, number, 1, 'a', 1, string, 2, 'b', 2, number]>,
      [string, number, 1, 'a', 2, 'b']
    >
  >,
  Expect<
    Equal<
      Unique<[unknown, unknown, any, any, never, never]>,
      [unknown, any, never]
    >
  >,
]

Pro Challenge

Unlock 102+ medium, hard, and extreme challenges to master advanced TypeScript.

One-time payment. Lifetime access.

Detailed Explanation

type IsEqual<A, B> =
  (<T>() => T extends A ? 1 : 2) extends (<T>() => T extends B ? 1 : 2)
    ? true
    : false;
 
type Contains<T extends any[], U> =
  T extends [infer First, ...infer Rest]
    ? IsEqual<First, U> extends true
      ? true
      : Contains<Rest, U>
    : false;
 
type Unique<T extends any[], Acc extends any[] = []> =
  T extends [infer First, ...infer Rest]
    ? Contains<Acc, First> extends true
      ? Unique<Rest, Acc>
      : Unique<Rest, [...Acc, First]>
    : Acc;

How it works:

This challenge helps you understand precise type equality checking and recursive tuple filtering, and how to apply these concepts in real-world scenarios.

This challenge is originally from here.

Share this challenge