이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.
쉽게 말하면 제네릭 B를 기반으로 조합할 수 있는 E와 M을 유니온 타입으로 뽑으면 된다.
(근데 조금 애매한게, E의 경우 중복해서 정의할 수 있는지를 잘 모르겠다)
type BEM<B extends string, E extends string[], M extends string[]> =
M extends [infer F extends string, ...infer O extends string[]] ?
`${BEM<B, E, []>}--${F}` | `${BEM<B, E, O extends [] ? never : O>}` :
E extends [infer F extends string, ...infer O extends string[]] ?
`${BEM<B, [], M>}__${F}` | `${BEM<B, O extends [] ? never : O, M>}` :
`${B}`
type A = BEM<'btn', ['price'], []>
type B = BEM<'btn', ['price'], ['warning', 'success']>
type C = BEM<'btn', ['a','b'], ['x','y']>
나의 경우 재귀로 풀려고... 시도해보았다.
이 경우 type C는 다음과 같이 나온다.
만약 E를 중복해서 리턴하게 하고 싶은 경우 다음과 같이 작성하면 된다.
type BEM<B extends string, E extends string[], M extends string[]> =
M extends [infer F extends string, ...infer O extends string[]] ?
`${BEM<B, E, []>}--${F}` | `${BEM<B, E, O extends [] ? never : O>}` :
E extends [infer F extends string, ...infer O extends string[]] ?
`${BEM<B, O, M>}__${F}` :
`${B}`
E의 `${BEM<B, O, M>}__${F}` 부분만 바꿔주면 된다.
이 경우 type C는 다음과 같다.
아마 이 코드 말고, 맨위의 코드가 정답일 것이다.
내가 작성한 코드를 해석해보자.
type BEM<B extends string, E extends string[], M extends string[]> : 이런 부분들은 알거라고 생각하고 넘어가겠다.
M extends [infer F extends string, ...infer O extends string[]] ? : 나는 재귀로 이 문제를 해결할 것이기 때문에, 뒤에 나오는 M을 먼저 다뤘다. M에서 원소를 하나씩 꺼내자.
`${BEM<B, E, []>--${F}` | `${BEM<B, E, O extends [] ? never : O>}` : Element가 처리된 문자열을 받기 위해 `BEM<B, E, []>--${F}`를 받고 유니온 타입을 만들어 주기 위해 뒤에 | `${BEM<B, E, O extends [] ? never : O>}`를 붙여준다. 여기서 O가 빈 배열이면 never를 리턴하게 하여 M이 없는 값이 나오지 않도록 해준다.
E도 위와 같이 해석할 수 있다.
어렵다. 내가 푼 방법으로 하면 진짜 어렵다.
그래서 다른 사람들의 답을 봐보았다.
type BEM<B extends string, E extends string[], M extends string[]> = `${B}${E extends []
? ''
: { [K in keyof E]: `__${E[K]}` }[number]}${M extends [] ? '' : { [K in keyof M]: `--${M[K]}` }[number]}`
`${B}${E extends [] ? '' : { [K in keyof E] : `__${E[K]}` }[number]} : E가 빈 배열이면 빈 문자열을 리턴하고, 아니라면 E의 key(이 경우엔 배열의 인덱스 이므로 객체를 배열로 나타내겠다는 뜻)을 뽑아서 각 키 값(0, 1, 2 ...)에 대해 값이 `__${E[K]}`가 담긴 배열을 만들고 [number]로 각 원소들을 뽑겠다는 뜻이다. 즉, E에 담긴 원소가 B_E 형태로 하나씩 유니온 타입으로 뽑힌다.
${M extends [] ? '' : { [K in keyof M] : `--${M[K]}` }[number]}` : 위와 같다.
이렇게 작성하면 정말 간단하다... 여러분들은 재귀같은거 쓰지 말자.
'Language > Typescript' 카테고리의 다른 글
타입챌린지 : 4179-Flip (medium) (0) | 2023.09.16 |
---|---|
타입챌린지 : 3376-InorderTraversal (medium) (0) | 2023.09.15 |
타입챌린지 : 3243-FlattenDepth (medium) (0) | 2023.05.30 |
타입챌린지 : 3196-Flip Arguments (medium) (0) | 2023.05.26 |
타입챌린지 : 3192-Reverse (medium) (0) | 2023.05.25 |