🔩
テンプレートリテラル型でReplaceをする
テンプレートリテラル型とは
type TemplateLiteralType = `dango-${ 'oishii' | 'kawaii' | 'daisuki' }`;
// dango-oishii | dango-kawaii | dango-daisuki
こんなやつです。
やってみる
こんなかんじです。
export type Replace<
T extends string,
S extends string,
D extends string,
A extends string = ''
> = T extends `${infer L}${S}${infer R}`
? Replace<R, S, D, `${A}${L}${D}`>
: `${A}${T}`;
type Replaced = Replace<'dango-oishii', '-', '_'>;
// -> dango_ohagi
解説
まずは型引数から。
T
には置き換える前の元の文字列を、S
には置き換える部分の文字列を、D
には置き換える後の文字列を指定します。
A
は、置き換える前の文字列の前に付ける文字列を指定します。
T extends `${infer L}${S}${infer R}`
この部分は置き換える部分の位置を取得をするために、T が (文字列)S(文字列)
という形になっているかを判断します。
もしそうなっているのであれば
? Replace<R, S, D, `${A}${L}${D}`>
Replace
にR
を1つめの引数に、S
, D
の位置は変わらず、4つめの引数には ${A}${L}${D}
を指定します。
export type Replace<
T extends string // R',
S extends string, // S
D extends string, // D
A extends string = '' // `${A'}${L'}${D'}`
> = T extends `${infer L}${S}${infer R}` // <- これには当てはまらない
? Replace<R, S, D, `${A}${L}${D}`>
: `${A}${T}`; // <- ここが返される
そうすると、T
が R'
という形になりR'
にS
があれば繰り返し、なければ${infer L}${S}${infer R}
には当てはまらなくなります。
: `${A}${T}`;
この部分のA
に${A'}${L'}${D'}
が入り、T
には R'
が入ります。
例
dango-oishii
の-
を_
に置き換える
type Replaced = Replace<'dango-oishii', '-', '_'>
↓
export type Replace<
T extends string // 'dango-oishii'
S extends string, // '-'
D extends string, // '_'
A extends string = ''
> = T extends `${infer L}${S}${infer R}`
// 'dango' + '-' + 'ohagi'
? Replace<R, S, D, `${A}${L}${D}`> // <- これが返される
// Replace<'ohagi', '-', '_', '' + 'dango' + '_' >
: `${A}${T}`;
↓
export type Replace<
T extends string // 'ohagi'
S extends string, // '-'
D extends string, // '_'
A extends string = '' // '' + 'dango' + '_'
> = T extends `${infer L}${S}${infer R}`
// 'ohagi' -> よってここには当てはまらない
? Replace<R, S, D, `${A}${L}${D}`>
: `${A}${T}`;
// '' + 'dango' + '_' + 'ohagi' -> dango_ohagi
↓
dango_ohagi
が返される。
おためし
マウスをホバーして確かめてみてくださいまし。
Discussion