Przejdź do treści
webtype.orgUczyń switch wyczerpującym

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Wzorce

    Jak dostać błąd kompilacji, gdy ktoś doda przypadek do unii i zapomni go obsłużyć?

    Zawęź każdy przypadek i przypisz resztę do `never`. Gdy unia urośnie, reszta przestaje być niczym i przypisanie zawodzi.

    Przepis

    type Shape =
      | { kind: 'circle'; r: number }
      | { kind: 'square'; side: number }
    
    function assertNever(value: never): never {
      throw new Error(`Unhandled: ${JSON.stringify(value)}`)
    }
    
    function area(shape: Shape): number {
      switch (shape.kind) {
        case 'circle':
          return Math.PI * shape.r ** 2
        case 'square':
          return shape.side ** 2
        default:
          return assertNever(shape)
      }
    }

    Build to kompiluje i sprawdza każdy wynik poniżej.

    Jak to działa

    1. 01
      function assertNever(value: never): never {

      Parametr o typie `never` nie przyjmuje niczego. Jedyną wartością, jaką da się przekazać, jest ta, którą kompilator już uznał za niemożliwą.

    2. 02
      return assertNever(shape)

      W gałęzi domyślnej z każdego znanego przypadku już wrócono, więc `shape` zawęziło się do `never` i to się kompiluje. Dodaj trzeci kształt, a przestanie — w tym wierszu, nazywając typ, o którym zapomniałeś.

    3. 03
      throw new Error

      Rzuca zamiast zwracać, bo wartość, która miała być niemożliwa, docierając w czasie wykonania jest błędem, a nie przypadkiem do wchłonięcia.

    Co dostajesz

    Gdzie to zawodzi

    Działa tylko wtedy, gdy każdy przypadek zwraca albo rzuca. `break`, który przechodzi do domyślnego, zostawia `shape` niezawężone, a sprawdzenie po cichu przestaje cokolwiek sprawdzać.

    Wniosek

    To najbardziej opłacalny wzorzec w tym języku. Zamienia „zapomnieliśmy obsłużyć nowy przypadek” z incydentu produkcyjnego w błąd kompilacji.

    Zobacz też

    Wzorce