제주도랏맨 2023. 9. 6. 03:01

 

출처: Type Challenges, https://github.com/type-challenges/type-challenges/blob/main/README.ko.md

 

189 - Awaited

Promise와 같은 타입에 감싸인 타입이 있을 때, 안에 감싸인 타입이 무엇인지 어떻게 알 수 있을까요?

 

type ExampleType = Promise<string>

type Result = MyAwaited<ExampleType> // string

 

풀이

type Thenable<T> = {
  then: (_: (_:T) => any) => any
}

type MyAwaited<T extends Thenable<any>> = T extends Thenable<infer U>
? U extends Thenable<any>
  ? MyAwaited<U>
  : U
: never

 

type MyAwaited<T extends object> = T extends { then : (onfulfilled: (value: infer U) => any) => any } 
? U extends { then : (onfulfilled: (value: any) => any) => any } 
  ? MyAwaited<U>
  : U
: never

 

원래는 아래와 같이 풀었는데 이해를 돕기 위해 이슈를 보고 위 코드의 Thenable을 추가했다.

위 코드에서 then은 객체 내부`{ ... }`의 key로 정확히 then이라는 이름을 가져야하지만,

onfulfilled나 value는 함수 내부`( .... )`의 파라미터의 타입을 지정하기 위해 넣은 이름일 뿐,

함수의 파라미터가 `onfulfilled`나 `value`와 같은 이름을 가져야하는 것이 아니다.

Thenable을 보면 특정 이름이 아니라 `_`를 사용하는 것을 볼 수 있다.

 

또, 주목하면 좋을 부분은 type 내에서 재귀가 가능하다는 것이다.

이쯤되면 단순히 타입을 지정하는 게 아니라 그냥 거의 함수 수준인데

extends를 이용한 조건문 삼항 연산자를 통해서 자기 자신을 다시 불러서 재귀적으로 type을 정의할 수 있다.

 

 

Reference

 

189 - Awaited - updated solution 11/08/2022 · Issue #18837 · type-challenges/type-challenges

Please comment if you find any improvements! type Thenable<T> = { then: (onfulfilled: (arg: T) => unknown) => unknown; } type MyAwaited<T extends Thenable<any> | Promise<any>> = T extends Promise<i...

github.com