문제
배열 타입 T를 받아 그 배열의 첫 번째 원소의 타입을 리턴하는 제네릭 First<T>
를 구현하세요.
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
풀이
문제에서 배열 타입 T를 받는다고 했으니, 대괄호<>
안에는 any\[\]
를 extends해야 한다. 여기까지 하면 errors의 빨간 줄이 사라진다.
이제 첫 번째 원소에 접근한다. TypeScript에서도 index를 활용해서 배열의 요소에 접근할 수 있다. 하지만 이 경우 빈 배열일 때의 예외처리가 불가능하다.
정답
스터디원들의 풀이가 포함되어있습니다!
// ============= Test Cases =============
import type { Equal, Expect } from "./test-utils";
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" }>
];
// ============= Your Code Here =============
// Solution 1
type First<T extends any[]> = T extends [] ? never : T[0];
// Solution 2
type First<T extends any[]> = T extends [infer U, ...any] ? U : never;
// Solution 3
type First<T extends any[]> = T["length"] extends 0 ? never : T[0];
빈 배열일 경우까지 예외처리를 추가한다.
Solution 1 : 조건문을 사용하여 만약 T가 빈 배열이라면 never
를 반환하고, 빈 배열이 아니라면 T의 첫 번째 원소를 반환한다.
Solution 2 : infer 키워드를 사용해서 T의 원소에 접근해보았다.
Solution 3 : 배열로 한정된 T의 length 프로퍼티에 접근해 그 값이 0인지를 체크해 빈 배열임을 확인했다.
'Frontend > Type-Challenge' 카테고리의 다른 글
[타입챌린지/type-challenge] Readonly (0) | 2023.01.26 |
---|---|
[타입챌린지/type-challenge] Pick (0) | 2023.01.26 |
[타입챌린지/type-challenge] Includes (2) | 2023.01.25 |
[타입챌린지/type-challenge] Awaited (0) | 2023.01.25 |
[타입챌린지/type-challenge] Hello World (0) | 2023.01.23 |