이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.
https://github.com/type-challenges/type-challenges
제네릭으로 배열과 Depth를 받아서, Depth만큼만 배열을 Flat하는 타입이다.
재귀를 어떻게 할지 방향성만 잡으면 생각보다 쉽다.
type FlattenDepth<T, N extends number = 1, U extends any[] = []> = U['length'] extends N ?
T :
T extends [infer F, ...infer O] ?
F extends any[] ? [...FlattenDepth<F, N, [...U, 0]>, ...FlattenDepth<O, N, U>] :
[F, ...FlattenDepth<O, N, U>] : T
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<FlattenDepth<[]>, []>>,
Expect<Equal<FlattenDepth<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,
Expect<Equal<FlattenDepth<[1, [2]]>, [1, 2]>>,
Expect<Equal<FlattenDepth<[1, 2, [3, 4], [[[5]]]], 2>, [1, 2, 3, 4, [5]]>>,
Expect<Equal<FlattenDepth<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, [[5]]]>>,
Expect<Equal<FlattenDepth<[1, [2, [3, [4, [5]]]]], 3>, [1, 2, 3, 4, [5]]>>,
Expect<Equal<FlattenDepth<[1, [2, [3, [4, [5]]]]], 19260817>, [1, 2, 3, 4, 5]>>,
]
type FlattenDepth<T, N extends number = 1, U extends any[] = []> : FlattenDepth라는 타입을 정의하는데 N은 Depth를 가리키고, 기본값이 1이고, U는 length비교를 통해 Depth를 확인하는 용도이다.
U['length'] extends N ? T : U의 길이가 N과 같으면 T를 바로 리턴하고 아니라면,
T extends [infer F, ...infer O] : T에서 첫번째 원소 F를 꺼내고
F extends any[] ? : F가 배열 형식이면
[...FlattenDepth<F, N, [...U, 0]>, ...FlattenDepth<O, N, U>] : 배열 F를 한 번 더 Flat해주기 위해 재귀하고, 나머지 O도 Flat을 해준다. 여기서 F는 이미 한 번 Flat되었기 때문에 U에 원소 하나를 추가해서 재귀를 돌리고, O의 경우는 Flat을 안했기 때문에 U를 그대로 가져간다.
[F, ...FlattenDepth<O, N, U>] : T : F가 배열이 아니라면 F는 그대로 리턴하고, FlattenDepth<O, N, U>를 통해 나머지를 마저 Flat한다. 그리고 T가 배열이 아니라면 T를 리턴한다.
'Language > Typescript' 카테고리의 다른 글
타입챌린지 : 3376-InorderTraversal (medium) (0) | 2023.09.15 |
---|---|
타입챌린지 : 3326-BEM style string (medium) (0) | 2023.09.14 |
타입챌린지 : 3196-Flip Arguments (medium) (0) | 2023.05.26 |
타입챌린지 : 3192-Reverse (medium) (0) | 2023.05.25 |
타입챌린지 : 3188-Tuple to Nested Object (medium) (0) | 2023.05.23 |