Przejdź do treści
webtype.org#230 permutation · par 5

Nr 230 · 7 sierpnia 2026 · Bezlitosna

Permutacja

Zaimplementuj `Permutation<T>`, aby zamieniał unię w unię wszystkich uporządkowań krotkowych jej elementów. `never` ma dokładnie jedną permutację: pustą krotkę.

01

Spróbuj rozwiązać samodzielnie

Par 5

Zagadka

permutation.ts
Podejście 1 z 5Jeszcze nie sprawdzone

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

Testy

4
  • Permutation<'a'>
    ['a']
  • Permutation<never>
    []
  • Permutation<'a' | 'b'>
    ['a', 'b'] | ['b', 'a']
  • Permutation<1 | 2>
    [1, 2] | [2, 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ć.

Archiwum
02

Rozwiązanie z komentarzem

Opublikowano 8 sierpnia 2026

Rozwiązanie

type Permutation<T, K = T> = [T] extends [never]
  ? []
  : K extends K
    ? [K, ...Permutation<Exclude<T, K>>]
    : never

Najczęstsza błędna odpowiedź

type Permutation<T> = T extends T ? [T] : never

To rozdziela się i owija każdy element we własną krotkę, dając `["a"] | ["b"]` — każdy element osobno, nigdy razem. Dla `never` odpowiada też `never`, bo dystrybucja po pustej unii nie daje nic zamiast pustej krotki.

Linia po linii

  1. [T] extends [never]

    Owinięcie w krotkę tłumi dystrybucję, co jest tu kluczowe: warunek dystrybutywny nad `never` daje `never` i przypadek bazowy nigdy by nie nastąpił.

  2. K extends K

    Warunek trywialnie prawdziwy, użyty wyłącznie dla efektu ubocznego: rozdziela `K`, więc gałąź poniżej wykonuje się raz na element unii. `K` domyślnie równa się `T`, zachowując nietkniętą kopię, gdy `T` jest zawężane przez `Exclude`.

Do zapamiętania

`K extends K` to idiom „rozdziel tę unię”, a `[T] extends [never]` — „nie rozdzielaj”. Znajomość obu i tego, którego wymaga dana linia, to większość różnicy między działającym kodem na typach a kodem po cichu zwracającym `never`.