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.
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).
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]
>
>,
]
Unlock 102+ medium, hard, and extreme challenges to master advanced TypeScript.
One-time payment. Lifetime access.
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:
IsEqual helper uses a technique involving deferred conditional types to perform exact type equality checks, correctly distinguishing between any, unknown, never, and literal typesContains helper recursively checks whether a tuple already includes a given type by comparing each element using IsEqualUnique type iterates through the input tuple T one element at a time, maintaining an accumulator Acc of already-seen unique elementsFirst, if it is already in Acc (checked via Contains), it is skipped; otherwise, it is appended to AccAcc is returned as the deduplicated resultThis 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.