Przejdź do treści
#237 unique-tuple · par 4

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Nr 237 · 20 sierpnia 2026 · Trudna

    Unikalne

    Zaimplementuj `Unique<T>`, aby usuwał duplikaty z krotki, zachowując pierwsze wystąpienie każdego. `Includes` z zagadki nr 227 jest dostępne.

    01

    Spróbuj rozwiązać samodzielnie

    Par 4

    Zagadka

    unique-tuple.ts
    type Includes<T extends readonly unknown[], U> =
      T extends readonly [infer H, ...infer R]
        ? Equal<H, U> extends true
          ? true
          : Includes<R, U>
        : false
    Podejście 1 z 4Jeszcze nie sprawdzone

    Zastąp ??? — rozwiązanie sprawdzamy przypadkami poniżej. Tab wcina; naciśnij Escape, a potem Tab, by wyjść fokusem.

    Testy

    4
    • Unique<[1, 2, 2, 3, 1]>
      [1, 2, 3]
    • Unique<[]>
      []
    • Unique<['a', 'b']>
      ['a', 'b']
    • Unique<[1, 1, 1]>
      [1]

    Jak oceniamy test Dokładna równość typów, nie przypisywalność — przecięcie to nie to samo co spłaszczony obiekt.

    Jak poszło innym

    Tę zagadkę rozwiązało jak dotąd mniej niż 5 osób. Rozkład pojawi się, gdy próbka będzie na tyle duża, by coś znaczyć.

    Gra na krótkim dystansie

    Najmniej znaków

    Nie ma jeszcze publicznych wyników.

    Archiwum
    02

    Rozwiązanie z komentarzem

    Opublikowano 21 sierpnia 2026

    Rozwiązanie

    type Unique<
      T extends readonly unknown[],
      Acc extends unknown[] = [],
    > = T extends readonly [infer H, ...infer R]
      ? Includes<Acc, H> extends true
        ? Unique<R, Acc>
        : Unique<R, [...Acc, H]>
      : Acc

    Najczęstsza błędna odpowiedź

    type Unique<T extends readonly unknown[]> =
      T extends readonly [infer H, ...infer R]
        ? Includes<R, H> extends true
          ? Unique<R>
          : [H, ...Unique<R>]
        : []

    To patrzy w przód, zamiast pamiętać. Gdy element powtarza się dalej, odrzuca *pierwsze* wystąpienie i zachowuje ostatnie, więc `[1, 2, 2, 3, 1]` daje `[2, 3, 1]`. Elementy są dobre, kolejność nie.

    Linia po linii

    1. Acc extends unknown[] = []

      Parametr typowy z wartością domyślną to sposób, w jaki funkcja na typach niesie stan. Wywołujący nigdy go nie podaje; każde wywołanie rekurencyjne przekazuje rosnący wynik dalej.

    2. Includes<Acc, H>

      Test przynależności działa na tym, co już zachowano, a nie na tym, co dopiero nadejdzie. To właśnie różnica między zachowaniem pierwszego a ostatniego wystąpienia.

    3. : Acc

      Gdy wejście się wyczerpie, akumulator *jest* odpowiedzią, więc zwracamy go wprost, zamiast składać wynik przy wychodzeniu. To kształt rekurencji ogonowej, a TypeScript obsługuje go mniejszym stosem niż formę głowa-ogon.

    Do zapamiętania

    Parametr akumulatora zamienia rekurencję budującą wstecz na budującą wprzód. Kosztuje jeden parametr typowy, a daje poprawną kolejność i głębszy limit rekurencji.

    Wykorzystuje