PercentageParser<Str>
使用法
tstype PString1 = ''
type PString2 = '+85%'
type PString3 = '-85%'
type PString4 = '85%'
type PString5 = '85'
type R1 = PercentageParser<PString1> // expected ['', '', '']
type R2 = PercentageParser<PString2> // expected ["+", "85", "%"]
type R3 = PercentageParser<PString3> // expected ["-", "85", "%"]
type R4 = PercentageParser<PString4> // expected ["", "85", "%"]
type R5 = PercentageParser<PString5> // expected ["", "85", ""]
文字列を引数にとって、符号、数字、単位に分ける
定義
ts// prettier-ignore
type PercentageParser<Str extends string> =
Str extends `${Sign<Str>}${infer N}${Unit<Str>}`
? [Sign<Str>, N, Unit<Str>]
: never;
// prettier-ignore
type Sign<Str extends string>
= Str extends `+${string}` ? '+'
: Str extends `-${string}` ? '-'
: '';
type Unit<Str extends string>
= Str extends `${string}%` ? '%'
: '';
ポイント
Str extends \
${Sign<Str>}${infer N}${Unit<Str>}\
の部分
unionで '+'|'-'|''
とやっているわけではない
扱いづらいのはnumberの部分なのでそこを残す
infer N
前からと、後ろからパターンマッチを同時にやっている感じ
ts// prettier-ignore
type PercentageParser<A extends string>
= A extends `${CheckPrefix<infer L>}${infer R}`
? [L, ...CheckSuffix<R>]
: ['', ...CheckSuffix<A>];
type CheckPrefix<T> = T extends '+' | '-' ? T : never;
type CheckSuffix<T> = T extends `${infer P}%` ? [P, '%'] : [T, ''];
記述量が少ない
先に符号だけわけて、後から残りを処理する
CheckPrefix<infer L>
の部分がおもろい

こうすることで、パターンマッチに名前をつけてる感じのことをしている
普通に書いたらこうなるはず
tstype PercentageParser<A extends string>
= A extends `${infer S}${infer R}`
? S extends '+' | '-'
? [S, ...CheckSuffix<R>]
: ['', ...CheckSuffix<A>] // ①
: ['', ...CheckSuffix<A>]; // ②
type CheckSuffix<T> = T extends `${infer P}%` ? [P, '%'] : [T, ''];
文字列のパターンマッチで S
を取り出した後に、
S
が '+'
か '-'
かをチェックすることになる
イメージこんな感じ
tstype Hoge<A extends string>
= A extends `${T: '+'|'-'}${infer R}`
? T
: never;
'+'|'-'
にマッチさせつつ、 T
という名前をつけている
でもそんな汎用性ないか

1文字しか無理だし