본문 바로가기

FE/type-challenge

9. DeepReadonly

728x90

문제

객체의 프로퍼티와 모든 하위 객체를 재귀적으로 읽기 전용으로 설정하는 제네릭 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`

cases

type cases = [
  Expect<Equal<DeepReadonly<X>, Expected>>,
]

type X = {
  a: () => 22
  b: string
  c: {
    d: boolean
    e: {
      g: {
        h: {
          i: true
          j: 'string'
        }
        k: 'hello'
      }
      l: [
        'hi',
        {
          m: ['hey']
        },
      ]
    }
  }
}

type Expected = {
  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 DeepReadonly<T> = {
  readonly [key in keyof T]: keyof T[key] extends never ? T[key] : DeepReadonly<T[key]>
}

풀이

조건

  1. T의 모든 값이 readonly여야 한다.
  1. T의 내부의 객체도 readonly여야 한다.

해설

readonly를 구현한다.

type DeepReadonly<T> = {
  readonly [key in keyof T]: T[key]
}

T[key]를 확인해서 object면 재귀적으로 DeepReadonly를 적용한다.

type DeepReadonly<T extends object> = {
  readonly [key in keyof T]: T[key] extends object ? DeepReadonly<T[key]> : T[key]
}

위의 코드는 function, array 등의 경우에 실패한다.

모두 extends object를 만족하기 때문인데, 이를 회피하기 위해서 key 값을 확인하는 로직을 추가한다.

type DeepReadonly<T> = {
  readonly [key in keyof T]: keyof T[key] extends never ? T[key] : DeepReadonly<T[key]>
}

혹시 오류나 개선점이 있다면 댓글 부탁드립니다.

728x90

'FE > type-challenge' 카테고리의 다른 글

12. Chainable  (0) 2023.09.05
10. TupleToUnion  (0) 2023.09.04
8. Readonly2  (0) 2023.09.01
3. Omit  (0) 2023.08.31
2. ReturnType  (0) 2023.08.30