bh2980.dev

9 - Deep Readonly

  • #Type Challenges
  • #TypeScript

질문

객체의 프로퍼티와 모든 하위 객체를 재귀적으로 읽기 전용으로 설정하는 제네릭 DeepReadonly<T>를 구현하세요.

이 챌린지에서는 타입 파라미터 T를 객체 타입으로 제한하고 있습니다. 객체뿐만 아니라 배열, 함수, 클래스 등 가능한 다양한 형태의 타입 파라미터를 사용하도록 도전해 보세요.

type X = {
  x: {
    a: 1
    b: 'hi'
  }
  y: 'hey'
}

type Expected = {
  readonly x: {
    readonly a: 1
    readonly b: 'hi'
  }
  readonly y: 'hey'
}

type Todo = DeepReadonly<X> // should be same as `Expected`

/* _____________ 테스트 케이스 _____________ */
import type { Equal, Expect } from '@type-challenges/utils' type cases = [ Expect<Equal<DeepReadonly<X1>, Expected1>>, Expect<Equal<DeepReadonly<X2>, Expected2>>, ] type X1 = { a: () => 22 b: string c: { d: boolean e: { g: { h: { i: true j: 'string' } k: 'hello' } l: [ 'hi', { m: ['hey'] }, ] } } } type X2 = { a: string } | { b: number } type Expected1 = { readonly a: () => 22 readonly b: string readonly c: { readonly d: boolean readonly e: { readonly g: { readonly h: { readonly i: true readonly j: 'string' } readonly k: 'hello' } readonly l: readonly [ 'hi', { readonly m: readonly ['hey'] }, ] } } } type Expected2 = { readonly a: string } | { readonly b: number }

선행 지식

  1. object, Object, {} 타입

    object : 원시 타입을 제외한 모든 객체 타입(함수, 배열 등 포함)

    Object : JS의 Object에 대응하는 매우 넓은 타입.(실무에서 필터로 사용하기엔 비권장)

    {} : nullundefined를 제외한 모든 타입

  2. 배열의 키

    배열도 객체이므로 keyof를 통해 순회 가능하다.

  3. readonly

    any[] extends readonly any[] ? true : false // true

    할당(대입) 가능성 기준으로, readonly 리스트 타입은 “쓰기 불필요”라 요구사항이 약하므로 더 넓다. 따라서 mutable 리스트는 readonly 리스트에 할당 가능하다.