ํƒ€์ž…์ฑŒ๋ฆฐ์ง€ [์‰ฌ์›€] ๋‚œ์ด๋„ ์ค‘ ์ธ์‚ฌ์ดํŠธ ์ •๋ฆฌ

    โœ… 1. 14 - First

    ๋ฌธ์ œ: ๋ฐฐ์—ด์˜ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ์˜ ํƒ€์ž…์„ ์ถ”์ถœํ•˜๋ผ.

    type arr1 = ['a', 'b', 'c']
    type arr2 = [3, 2, 1]
    
    type head1 = First<arr1> // expected to be 'a'
    type head2 = First<arr2> // expected to be 3
    
    type cases = [
      Expect<Equal<First<[3, 2, 1]>, 3>>,
      Expect<Equal<First<[() => 123, { a: string }]>, () => 123>>,
      Expect<Equal<First<[]>, never>>,
      Expect<Equal<First<[undefined]>, undefined>>,
    ]
    
    type errors = [
      // @ts-expect-error
      First<'notArray'>,
      // @ts-expect-error
      First<{ 0: 'arrayLike' }>,
    ]
    type First<T extends any[]> = T extends [] ? never : T[0];
    • ๋นˆ ๋ฐฐ์—ด์ด๋ฉด never, ์•„๋‹ˆ๋ฉด T[0]์œผ๋กœ ์ฒซ ์š”์†Œ ๋ฐ˜ํ™˜
    • ๋ฐฐ์—ด ์ œ์•ฝ: T extends any[]

    โœ… 2. 43 - Exclude

    ๋ฌธ์ œ: ์œ ๋‹ˆ์–ธ ํƒ€์ž… T์—์„œ U์— ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์„ ์ œ๊ฑฐํ•˜๋ผ.

    type cases = [
      Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a'>, 'b' | 'c'>>,
      Expect<Equal<MyExclude<'a' | 'b' | 'c', 'a' | 'b'>, 'c'>>,
      Expect<Equal<MyExclude<string | number | (() => void), Function>, string | number>>,
    ]
    type MyExclude<T, U> = T extends U ? never : T;
    • ํ•ต์‹ฌ: ์กฐ๊ฑด๋ถ€ ํƒ€์ž…์˜ ๋ถ„์‚ฐ ์„ฑ์งˆ
    • 'a' | 'b' | 'c', 'a' → 'b' | 'c'

    โœ… 3. 189 - Awaited

    ๋ฌธ์ œ: Promise ํƒ€์ž…์—์„œ ๋‚ด๋ถ€ ๊ฐ’์„ ๊บผ๋‚ด๋ผ (์žฌ๊ท€์ ์œผ๋กœ).

    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>>,
      Expect<Equal<MyAwaited<T>, number>>,
    ]
    type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer U> 
    	? U extends PromiseLike<any> 
        	? MyAwaited<U> 
            : U 
        : never;
    • infer๋กœ ๋‚ด๋ถ€ ํƒ€์ž… ๊บผ๋ƒ„
    • ์ค‘์ฒฉ๋œ Promise๋„ ์žฌ๊ท€๋กœ ์ฒ˜๋ฆฌ
    • PromiseLike ์ œ์•ฝ์œผ๋กœ thenable ๋Œ€์‘

    โœ… 4. 533 - Concat

    ๋ฌธ์ œ: ๋ฐฐ์—ด T, U๋ฅผ ์ด์–ด๋ถ™์ธ ๊ฒฐ๊ณผ ํƒ€์ž…์„ ๋งŒ๋“ค๋ผ.

    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']>>,
    ]
    
    // @ts-expect-error
    type error = Concat<null, undefined>
    type Concat<T extends readonly unknown[], U extends readonly unknown[]> = [...T, ...U];
    • ํŠœํ”Œ ์Šคํ”„๋ ˆ๋“œ๋กœ ๊ฐ„๋‹จํžˆ ๋ณ‘ํ•ฉ

    โœ… 5. 898 - Includes

    ๋ฌธ์ œ: ๋ฐฐ์—ด T์— ํƒ€์ž… U๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋ผ (Equal ๊ธฐ์ค€).

    type cases = [
      Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Kars'>, true>>,
      Expect<Equal<Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'>, false>>,
      Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 7>, true>>,
      Expect<Equal<Includes<[1, 2, 3, 5, 6, 7], 4>, false>>,
      Expect<Equal<Includes<[1, 2, 3], 2>, true>>,
      Expect<Equal<Includes<[1, 2, 3], 1>, true>>,
      Expect<Equal<Includes<[{}], { a: 'A' }>, false>>,
      Expect<Equal<Includes<[boolean, 2, 3, 5, 6, 7], false>, false>>,
      Expect<Equal<Includes<[true, 2, 3, 5, 6, 7], boolean>, false>>,
      Expect<Equal<Includes<[false, 2, 3, 5, 6, 7], false>, true>>,
      Expect<Equal<Includes<[{ a: 'A' }], { readonly a: 'A' }>, false>>,
      Expect<Equal<Includes<[{ readonly a: 'A' }], { a: 'A' }>, false>>,
      Expect<Equal<Includes<[1], 1 | 2>, false>>,
      Expect<Equal<Includes<[1 | 2], 1>, false>>,
      Expect<Equal<Includes<[null], undefined>, false>>,
      Expect<Equal<Includes<[undefined], null>, false>>,
    ]
    type Includes<T extends readonly unknown[], U> = T extends [infer First, ...infer Rest] 
    	? Equal<First, U> extends true 
        	? true 
            : Includes<Rest, U> 
        : false;
    • ์žฌ๊ท€๋กœ ๋ฐฐ์—ด ํƒ์ƒ‰
    • Equal์„ ์‚ฌ์šฉํ•ด ํƒ€์ž… ๋™๋“ฑ์„ฑ ๋น„๊ต

    โœ… 6. 3312 - Parameters

    ๋ฌธ์ œ: ํ•จ์ˆ˜ ํƒ€์ž…์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ํŠœํ”Œ์„ ์ถ”์ถœํ•˜๋ผ (Parameters ์ง์ ‘ ๊ตฌํ˜„).

    function foo(arg1: string, arg2: number): void {}
    function bar(arg1: boolean, arg2: { a: 'A' }): void {}
    function baz(): void {}
    
    type cases = [
      Expect<Equal<MyParameters<typeof foo>, [string, number]>>,
      Expect<Equal<MyParameters<typeof bar>, [boolean, { a: 'A' }]>>,
      Expect<Equal<MyParameters<typeof baz>, []>>,
    ]
    type MyParameters<T extends (...args: any[]) => any> 
    	= T extends (...args: infer P) => any 
        	? P 
            : never;
    • infer P๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก ์ถ”์ถœ
    • ํ•จ์ˆ˜ ํƒ€์ž… ์ œ์•ฝ: T extends (...args: any[]) => any
    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€