미라클 글쓰기 4일차
easy – Readonly
T의 모든 프로퍼티를 읽기 전용(재할당 불가)으로 바꾸는 내장 제네릭 Readonly<T>를 이를 사용하지 않고 구현하세요.
예시:
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
처음 풀었던 Pick과 유사한 문제로, Mapped Type의 순회를 익숙하게 하는 문제다.
이 문제를 풀기 위해 알아야 할 사전지식은 다음과 같다.
keyofOperator- Mapped Type
- Indexed Access Type
readonlyKeyword
제네릭 Type T의 모든 프로퍼티를 readonly로 변경하는 문제이므로, 모든 프로퍼티를 순회하면서 프로퍼티를 readonly로 바꾸면 된다.
type MyReadonly<T> = { readonly [k in keyof T]: T[k] }
easy – Awaited
문제 링크: https://github.com/type-challenges/type-challenges/tree/main/questions/00189-easy-awaited
by Maciej Sikora @maciejsikora
도전하기 English 简体中文 日本語
Promise와 같은 타입에 감싸인 타입이 있을 때, 안에 감싸인 타입이 무엇인지 어떻게 알 수 있을까요?
예시: 들어 Promise<ExampleType>이 있을 때, ExampleType을 어떻게 얻을 수 있을까요?
type ExampleType = Promise<string>
type Result = MyAwaited<ExampleType> // string
출처: original article by @maciejsikora
compile time에 recursion을 통해 타입을 추론하는 방법을 연습하는 문제로, 이런 방법이 있는 줄은 Type Challenge를 풀어보기 전에는 생각도 못했다.
사전에 알아야 할 지식은 다음과 같다.
- Conditional Type
inferKeyword
Conditional Type은 Ternary(Conditional) Operator를 type 에 사용, 조건에 따라 type을 분기한다.
type A = A extends B ? C : D;
Conditional Type의 특성에 따라 조건 분기문에 자기 자신의 Type을 넣을 수 있고, 이를 통해 재귀적인 타입 추론(!)이 가능하다.(어떤 방식인지 끝까지 보면 알 수 있다.)
주어진 문제는 Promise로 감싸인 내부의 타입을 compile time에 알아내는 것이므로, 주어진 제네릭 타입 T가 Promise인지 여부를 판별해 보자.
문제를 단계별로 해결하기 위해 일단은 T가 Promise<string> 인 경우만 가정해보면 다음과 같다.
type MyAwaited<T> = T extends Promise<string> ? string : T;
여기서 T가 Promise<number> 인 경우를 추가한다면
type MyAwaited<T> = T extends Promise<string> ?
string :
T extends Promise<number> ?
number :
T;
이런 식으로 지저분하게 계속 조건을 늘릴 수도 있지만, 우아하게 infer keyword를 이용해보자.
infer R 을 사용하여 다음과 같이 T 내부에 감싸여 있는 어떤 Type인지 결정되지 않은 Type을 표현할 수 있다.
type MyAwated<T> = T extends Promise<infer R> ? R : T;
가장 까다로운 케이스는 Promise를 Promise로 감싸는 형태다. 몇 겹을 감싸게 될런지 모르기 때문에
다음과 같이 conditional 분기에서 재귀적으로 타입을 추론해보자.
type MyAwaited<T> = T extends Promise<infer R> ?
R extends Promise<any> ?
MyAwaited<R> :
R:
T;
최종 test case까지 통과하려면 T가 반드시 Promise<?> 이면서 PromiseLike 하여야 하므로,
최종 답안은 다음과 같다.
type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer U> ?
U extends PromiseLike<any> ?
MyAwaited<U> :
U :
T;





댓글 남기기