Przejdź do treści
Uczyń obiekt głęboko tylko do odczytu

    ↑↓ ruch · ⏎ otwórz · esc zamknij

    Wzorce

    Jak zapobiec mutacji poniżej pierwszego poziomu właściwości, zamiast zamrażać tylko zewnętrzny typ obiektu?

    Zachowaj funkcje, przejdź rekurencyjnie przez tablice i zmapuj każdą właściwość obiektu z modyfikatorem readonly.

    Przepis

    type DeepReadonly<T> =
      T extends (...args: any[]) => unknown
        ? T
        : T extends readonly unknown[]
          ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
          : T extends object
            ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
            : T
    
    type Config = {
      api: { url: string; retries: number }
      tags: string[]
      format: (value: number) => string
    }
    
    type FrozenConfig = DeepReadonly<Config>

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

    Jak to działa

    1. 01
      T extends (...args: any[]) => unknown

      Funkcje są już wartościami wywoływalnymi; mapowanie ich składowych obiektowych zniszczyłoby sygnaturę wywołania.

    2. 02
      { readonly [K in keyof T]: DeepReadonly<T[K]> }

      Każda właściwość jest zamrażana, a jej wartość ponownie przechodzi przez tę samą decyzję.

    Co dostajesz

    Gdzie to zawodzi

    To niezmienność w czasie kompilacji, nie `Object.freeze`. Traktuje też instancje klas jak obiekty strukturalne, co może zaskakująco ujawnić składowe implementacji; w kodzie domenowym dodaj jawne przypadki typów wbudowanych i klas.

    Wniosek

    Rekurencyjne modyfikatory potrzebują reguł zatrzymania. Obsłuż funkcje i obiekty specjalne przed ogólną gałęzią obiektu.

    Zobacz też

    Wzorce