출처: Type Challenges, https://github.com/type-challenges/type-challenges/blob/main/README.ko.md
8 - Readonly 2
`T`에서 `K` 프로퍼티만 읽기 전용으로 설정해 새로운 오브젝트 타입을 만드는 제네릭 `MyReadonly2<T, K>`를 구현하세요. `K`가 주어지지 않으면 단순히 `Readonly<T>`처럼 모든 프로퍼티를 읽기 전용으로 설정해야 합니다.
interface Todo {
title: string
description: string
completed: boolean
}
const todo: MyReadonly2<Todo, 'title' | 'description'> = {
title: "Hey",
description: "foobar",
completed: false,
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
todo.completed = true // OK
풀이
type MyReadonly2<T, K extends keyof T = keyof T> = {
[P in keyof T as P extends K ? never : P]: T[P]
} & {
readonly [P in keyof T as P extends K ? P : never]: T[P]
}
먼저 문제에서 `// @ts-expect-error` 주석 부분이 있다.
// @ts-expect-error
type error = MyReadonly2<Todo1, 'title' | 'invalid'>
즉, 잘못된 키가 설정되는 것을 막아야하므로, `K`를 `K extends keyof T`로 설정한다.
그런데 문제에서 `K`가 주어지지 않으면 단순히 `Readonly<T>`처럼 모든 프로퍼티를 읽기 전용으로 설정해야 합니다.
라는 조건이 있기 때문에 K가 주어지지 않은 경우에 들어갈 기본값 역시 지정해주어야한다
K가 주어지지 않으면 모든 key를 readonly로 만들기 때문에 기본값을 T의 모든 key인 `keyof T`로 지정해준다.
{
[P in keyof T as P extends K ? never : P]: T[P]
} & {
readonly [P in keyof T as P extends K ? P : never]: T[P]
}
그 다음에는 Omit에서 사용했던 방식처럼 프로퍼티 Key를 as를 통해 다시 매핑하여 필터링하는데
만약 P가 K에 포함되지 않았다면 readonly를 붙여주지 않고, P가 K에 포함된다면 readonly를 붙여준다.
이 때 두 객체 타입을 &을 통해 합쳐주어 하나의 타입으로 기능하게 만든다.
'알고리즘 > Type Challenges' 카테고리의 다른 글
3 - Omit (0) | 2023.09.17 |
---|---|
2 - Get Return Type (0) | 2023.09.17 |
898 - Includes (0) | 2023.09.17 |
3312 - Parameters (0) | 2023.09.17 |
3060 - Unshift (0) | 2023.09.17 |