Skip to main content

Command Palette

Search for a command to run...

[type-challenges] Awaited / If / Concat

Published
2 min read

Awaited

설계 의도

  • 제네릭타입 T를 PromiseLike<any> 로 정의하여서 Promise, then 메서드 가진 함수 모두 받도록 처리

  • infer 사용해서 PromiseLike의 내부 타입 추출

  • 다중 Promise 중첩 처리에서 최종 결과 타입 풀어내기 위해서 재귀적 조건부 타입 사용

Promise<T> vs PromiseLike<T>

  • Promise<T>Promise 객체의 전체 API를 나타내는 반면, PromiseLike<T>then 메서드를 가진 모든 객체를 의미한다.

interface PromiseLike<T> {
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onfulfilled The callback to execute when the Promise is resolved.
     * @param onrejected The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of which ever callback is executed.
     */
    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}

코드

/* _____________ Your Code Here _____________ */
type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer U>
  ? U extends PromiseLike<any>
    ? MyAwaited<U>
    : U
  : never;

/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type X = Promise<string>
type Y = Promise<{ field: number }>
type Z = Promise<Promise<string | number>>
type Z1 = Promise<Promise<Promise<string | boolean>>>
type T = { then: (onfulfilled: (arg: number) => any) => any }

type cases = [
  Expect<Equal<MyAwaited<X>, string>>,
  Expect<Equal<MyAwaited<Y>, { field: number }>>,
  Expect<Equal<MyAwaited<Z>, string | number>>,
  Expect<Equal<MyAwaited<Z1>, string | boolean>>,
  Expec

If

설계 의도

  • 제네릭 타입 C가 true인지 조건 체크해서, 리턴타입 지정

  • boolean의 경우 분산 유니온타입(true | false extends true)으로 처리되기 때문에 truefalse를 모두 리턴하게 된다.

코드

 /* _____________ Your Code Here _____________ */

type If<C, T, F> = C extends true? T : F

/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<If<true, 'a', 'b'>, 'a'>>,
  Expect<Equal<If<false, 'a', 2>, 2>>,
  Expect<Equal<If<boolean, 'a', 2>, 'a' | 2>>,
]

Concat

설계 의도

  • 두 개의 튜플이나 배열을 하나로 결합하도록 처리

코드

/* _____________ Your Code Here _____________ */

type Concat<T extends readonly any[], U extends readonly any[]> = [...T,...U]

/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'

const tuple = [1] as const

type cases = [
  Expect<Equal<Concat<[], []>, []>>,
  Expect<Equal<Concat<[], [1]>, [1]>>,
  Expect<Equal<Concat<typeof tuple, typeof tuple>, [1, 1]>>,
  Expect<Equal<Concat<[1, 2], [3, 4]>, [1, 2, 3, 4]>>,
  Expect<Equal<Concat<['1', 2, '3'], [false, boolean, '4']>, ['1', 2, '3', false, boolean, '4']>>,
]

More from this blog

Conductor 워크스페이스마다 .env 파일 자동 복사하기

문제를 만나다 개인 프로젝트를 진행할 때 기능을 병렬로 구현하기 위해서 Conductor를 사용하고 있다. 여러 개의 워크 스페이스를 새로 만들 때마다 환경변수를 매번 수동 복사해야 하는 게 매우 귀찮았다. 워크트리 개념이 익숙하지 않아서 처음에는 워크트리 생성 시 모든 파일을 다 가져오는 줄 알았다. 워크트리의 동작 방식을 찾아보니, git에 저장된 파일만 생성된다는 걸 새로 알게 되었다. 도움 받은 블로그 글 링크 : Git에서 다수...

Dec 28, 20251 min read

[ts-challenges] Includes / Push / Unshift / Parameters

Includes 설계 의도 튜플 타입 T를 첫 번째 요소인 Head와 나머지 요소들인 Tail로 분리해서 추론한다. Head가 제네릭 U 타입과 동일하지 않으면 Includes 타입을 Tail에 대해 재귀적으로 다시 실행하면서 다음 요소 검사하기 boolean 타입의 경우, true와 false이 모두 할당가능하니까 엄격하게 동등한지 비교하기 위해서 Equal 헬퍼함수 사용 코드 type Equal<X, Y> = (<T>() => ...

May 23, 20253 min read

Untitled Publication

37 posts