이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.
제네릭 인자로 들어오는 배열 값의 원소에 배열이 있다면, 배열을 모두 제거해서 하나의 배열로 리턴하는 타입이다.
일단, 내가 생각한 첫 번째 답변을 봐보자.
type Flatten<T extends any[]> = T extends [infer F, ...infer O] ?
(F extends any[] ?
[...F, ...Flatten<O>] : [F, ...Flatten<O>]) :
[];
T가 배열이고, T의 첫 번째 원소가 배열이면 전개연산자를 이용해 재귀하는 형태로 작성해보았다.
하지만, 테스트케이스 4번에서 에러가 났다.
Flatten<[1, 2, [3, 4], [[[5]]]> 에서 [[[5]]]가 제대로 Flat이 되지 않았다... 배열 하나만 벗겨지고 나머지는 벗겨지지 않았다.
그 이유는 바로, F가 배열이 겹쳐있을 때 단순히 ...F로만 전개해주면 안되고, Flatten을 재귀를 이용해서 또 한 번 Flat해주어야 한다.
그리서 최종 답은 이렇다.
type Flatten<T extends any[]> = T extends [infer F, ...infer O] ?
(F extends any[] ? [...Flatten<F>, ...Flatten<O>] :
[F, ...Flatten<O>]) :
[];
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Flatten<[]>, []>>,
Expect<Equal<Flatten<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,
Expect<Equal<Flatten<[1, [2]]>, [1, 2]>>,
Expect<Equal<Flatten<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, 5]>>,
Expect<Equal<Flatten<[{ foo: 'bar'; 2: 10 }, 'foobar']>, [{ foo: 'bar'; 2: 10 }, 'foobar']>>,
]
T extends [infer F, ...infer O] ? : T가 첫 번째 원소 F와 나머지 배열 O로 나뉠 때, (여기서 T가 원소가 하나인 배열이어도 해당된다)
F extends any[] ? : F가 배열이라면,
[...Flatten<F>, ...Flatten<O>] : F를 재귀로 Flatten해주고(F가 배열이 여러겹 일 수 떄문에... [[[F]]] 같이.), O도 재귀로 Flatten 해준다.
[F, ...Flatten<O>] : F가 배열이 아니라면 F를 그대로 리턴하고, 나머지는 Flatten해준다.
[] : T가 배열이 아니라면(마지막 재귀에서) 빈 배열을 리턴한다.
'Language > Typescript' 카테고리의 다른 글
타입챌린지 : 529-Absolute (medium) (0) | 2023.04.10 |
---|---|
타입챌린지 : 527-Append to object (medium) (0) | 2023.04.07 |
타입챌린지 : 298-Length of String (medium) (0) | 2023.04.05 |
타입챌린지 : 296-Permutation (medium) (0) | 2023.04.04 |
타입챌린지 : 191-Append Argument (medium) (0) | 2023.03.31 |