틀린 부분 있으면 댓글로 알려주세요!
시작 전
먼저 배열에 대해 알아볼게요.
자바스크립트에서 배열의 타입은 object입니다.
그럼 어떻게 구성되어 있는 걸까요?
const a = [1, 2, 3]
으로 알아볼게요.
{ 0: 1, 1: 2, 2: 3, length: 3 }
꼴의 특수한 객체라는 사실을 알 수 있어요. 특수하다고 말한 이유는 대괄호 표기법을 사용할 때 2가지 방법이 가능하기 때문이에요.
참고로 key들의 타입은 number입니다. 타입스크립트를 통해 알 수 있어요.
interface myArray<T> {
[n: number]: T;
}
const arr: myArray<number> = [1, 2, 3];
interface myArray<T> {
[n: string]: T;
}
const arr: myArray<number> = [1, 2, 3]; // 에러
지금까지 배열은 key 타입이 number로 이루어진 특수한 객체라는 사실을 배웠어요.
interface ReadonlyArray<T>{
...
readonly [n: number]: T;
...
}
이제 우린 ReadonlyArray<T>가 배열을 의미한다는 걸 알죠.
시작
제가 이해를 못했던 부분은 재귀를 할 때마다 배열이 한 차원씩 내려간다는 거였어요. 그래서 이 부분을 중점적으로 설명할게요.
예시는 [1, 2, [3, 4], [[5, 6]]].flat(2)
로 할게요.
1.
flat<A, D extends number = 1>(
this: A,
depth?: D
): FlatArray<A, D>[]
A는 (number | number[] | number[][])[]이고,
D는 2입니다.
2.
type FlatArray<Arr, Depth extends number> = {
"done": Arr,
"recur": Arr extends ReadonlyArray<infer InnerArr>
? FlatArray<InnerArr, [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20][Depth]>
: Arr
}[Depth extends -1 ? "done" : "recur"];
Depth가 2라서 "recur"로 갑니다.
Arr은 (number | number[] | number[][])[]겠죠?
Arr을 다르게 표현해 볼게요.
{ 0: number, 1: number[], 2: number[][], length: 3 }
extends가 있으니 ReadonlyArray를 만족하는 Arr을 찾아야 해요.
그리고 InnerArr은 ReadonlyArray<T>에서 T에 해당하겠죠? 그리고 T는 number | number[] | number[][]에요.
따라서, InnerArr은 number | number[] | number[][]죠.
3.
재귀를 하네요.
Arr은 이제 number | number[] | number[][]고,
Depth는 1이에요. "recur"로 갑니다.
마찬가지로 ReadonlyArray와 비교해야죠.
number는 배열이 아니므로 제외됩니다.
number[]는 { 0: number, length: 1}이고,
number[][]는 {0: number[], length: 1}입니다.
그래서 InnerArr은 number | number[]죠.
4.
재귀를 합니다.
Arr은 이제 number | number[]고,
Depth는 0이에요. "recur'로 갑니다.
3과 같이 수행하면 InnerArr은 number가 됩니다.
5.
재귀를 합니다.
Depth가 -1이네요? "done"으로 갑니다.
Arr가 number니까 number가 리턴됩니다.
6.
flat<A, D extends number = 1>(
this: A,
depth?: D
): FlatArray<A, D>[]
FlatArray<A, D>가 number라는 걸 알았어요,
그래서 flat은 number[]를 반환하는 거죠.
이러한 과정을 거치기 때문에,
[1, 2, [3, 4], [[5, 6]]].flat(2)
의 타입이 number[]가 됩니다.
도움이 되셨으면 좋겠네요 :)