이 글은 제가 타입챌린지를 하면서 해석한 내용을 적는 글입니다. 틀린 내용이 있으면 댓글 달아주시면 감사하겠습니다.
설명에는 정규표현식 어쩌구 저쩌구 적혀있는데... 굳이 읽을 필요는 없는 것 같다.
제네릭인자를 [- or +, number, percentage] 로 분해하여 리턴하는 타입이다.
일단, 나의 첫번째 답을 봐보자.
// 정답이긴하나... 노가다이다.
type PercentageParser<A extends string> = A extends '%' ? ['', '', '%'] : A extends `${infer F}${infer O}%` ?
F extends '+' | '-' ? [F, O, '%'] : ['', `${F}${O}`, '%'] :
A extends `${infer F}${infer O}` ?
F extends '+' | '-' ? [F, O, ''] : ['', A, ''] :
['', '', '']
정답이긴하나... 노가다를 통해서 정의를 하였기 때문에 보기가 힘들고 이해하기 어렵다.
두번째 답은 재귀를 이용해서 풀어보았다.
type PercentageParser<A extends string, X extends string='', Y extends string=''> = A extends `${infer F}${infer O}` ?
F extends '+' | '-' ? PercentageParser<O, F> :
F extends '%' ? [X, Y, '%'] : PercentageParser<O, X, `${Y}${F}`> :
[X, Y, '']
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type Case0 = ['', '', '']
type Case1 = ['+', '', '']
type Case2 = ['+', '1', '']
type Case3 = ['+', '100', '']
type Case4 = ['+', '100', '%']
type Case5 = ['', '100', '%']
type Case6 = ['-', '100', '%']
type Case7 = ['-', '100', '']
type Case8 = ['-', '1', '']
type Case9 = ['', '', '%']
type Case10 = ['', '1', '']
type Case11 = ['', '100', '']
type cases = [
Expect<Equal<PercentageParser<''>, Case0>>,
Expect<Equal<PercentageParser<'+'>, Case1>>,
Expect<Equal<PercentageParser<'+1'>, Case2>>,
Expect<Equal<PercentageParser<'+100'>, Case3>>,
Expect<Equal<PercentageParser<'+100%'>, Case4>>,
Expect<Equal<PercentageParser<'100%'>, Case5>>,
Expect<Equal<PercentageParser<'-100%'>, Case6>>,
Expect<Equal<PercentageParser<'-100'>, Case7>>,
Expect<Equal<PercentageParser<'-1'>, Case8>>,
Expect<Equal<PercentageParser<'%'>, Case9>>,
Expect<Equal<PercentageParser<'1'>, Case10>>,
Expect<Equal<PercentageParser<'100'>, Case11>>,
]
배열에 들어 갈 값들을 제네릭 X와 Y에 저장해서 재귀로 넘기는 방식이다.
A extends `${infer F}${infer O}` ? : A가 첫번째 문자 F와 나머지 문자열 O로 나뉠 때,
F extends '+' | '-' ? PercentagerParfser<O, F> : F가 +나-라면, X에 부호를 저장해서 나머지 O를 넘기면서 재귀를 호출하고,
F extends '%' ? [X, Y, '%'] : PercentageParser<O, X, `${Y}${F}`> : F가 부호가 아닐 때, F가 %라면 [X, Y, '%']를 리턴하고 아니라면 현재값을 Y에 담아서 재귀를 호출한다.
[X, Y, ''] : 재귀가 마지막까지 호출되었다면, [X, Y, ''] 를 호출한다.
다른 분들의 답을 봐보자.
type CheckPrefix<T> = T extends '+' | '-' ? T : never;
type CheckSuffix<T> = T extends `${infer P}%` ? [P, '%'] : [T, ''];
type PercentageParser<A extends string> = A extends `${CheckPrefix<infer L>}${infer R}` ?
[L, ...CheckSuffix<R>] : ['', ...CheckSuffix<A>];
와~ 진짜 천재인거같다.
문자열을 분산 조건부 타입으로 나눌 때, `${CheckPrefix<infer L>}${infer R}` 과 같이 나눌 수 있다는 걸 처음 알게되었다.
이렇게 나누면 자동적으로 L에 첫 문자가 들어가게 된다... 크.. 오늘도 역시 한수 배우고 간다.
'Language > Typescript' 카테고리의 다른 글
타입챌린지 : 2257-MinusOne (medium) (0) | 2023.05.04 |
---|---|
타입챌린지 : 2070-Drop Char (medium) (0) | 2023.05.01 |
타입챌린지 : 1367-Remove Index Signature (medium) (0) | 2023.04.24 |
타입챌린지 : 1130-ReplaceKeys (medium) (0) | 2023.04.22 |
타입챌린지 : 1097-IsUnion (medium) (0) | 2023.04.21 |