type Split<
S extends string,
D extends string,
> = S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [S]
좀 어려웠던 부분이 ${infer T}${D}${infer U} 부분이어서, 이해한 방식대로 하나씩 살펴보겠습니다
일단 infer는 쉽게 말하면 조건부 타입에서 TS에서 추론한 값을 사용하겠다 라는 의미이다
type Parse<S extends string> = S extends `${infer T}${"/"}${infer U}`
? `${T}+${U}`
: never
let hello: Parse<"hello/world"> // hello+world
만약 S의 타입에 / 라는 문자열이 들어간다면, 해당 부분은 참이기 때문에 T랑 U는 /의 앞뒤부분,
한마디로 T는 hello , U는 world로 추론이 될 것이다
/가 없다면 , 조건이 거짓이기 때문에 a는 never다시 Split으로 돌아가서,
type Split<
S extends string,
D extends string,
> = S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [S]
S를 나눌 문자열, D는 기준점이 된다
Split<'a,b,c',','>
1) T는 'a' , U는 'b,c'로 추론 => ['a',...Split<'b,c'>,',']
2) T는 'b' , U는 'c'로 추론 => ['b',...Split<'c',','>]
3) 'c' extends `${infer T},${infer U}` 부분은 거짓이기 때문에, 타입은 ['c'] 가 되면서 재귀 리턴
이후 하나씩 거슬러 올라가면 최종적으로 ['a',b','c'] 라는 결과값을 가질 수 있게 된다