TypeScriptで、既存の型から一部のプロパティを、プロパティ名の部分一致で抽出・削除する方法をメモ。
環境
TypeScript v4.7.4 で確認。
プロパティ名の部分一致での抽出・削除方法
テンプレートリテラル内にUnionを用いると、すべての組み合わせの文字列リテラルのUnionとなる。
文字列から型定義が行えるこの機能は、Template Literal Typesというらしい。
TypeScript: Documentation - Template Literal Types
Extract
の第2引数に prefix${string}
のように指定することで、プロパティ名を部分一致で抽出できる。
Extract
の結果を、 Pick
に渡してやれば抽出、 Omit
に渡してやれば削除できる。
// val1 | val2 | value1 | value2 のUnionになる type PropertyNames = `${`val${'' | 'ue'}`}${1 | 2}` // Unionの各値をプロパティ名とした型を用意 type Properties = Record<PropertyNames, string> // value1 | value2 のUnion type TargetPropertyNames = Extract<keyof Properties, `value${string}`> // Record<'value1' | 'value2', string> と同様 type PickProperties = Pick<Properties, TargetPropertyNames> // Record<'val1' | 'val2', string> と同様 type OmitProperties = Omit<Properties, TargetPropertyNames>
実装例
以下のような type
を用意。
type PropertySuffix = 1 | 10 | 100 | 'Value' | 'True' | 'False' | true | false // { [Key in `string${PropertySuffix}`]: string } & ... と同様 type Properties = Record<`string${PropertySuffix}`, string> & Record<`number${PropertySuffix}`, number> & Record<`boolean${PropertySuffix}`, boolean> type PropertyKeys = keyof Properties
任意の文字列での一致
${string}
がワイルドカードのように使用できる。
- 前方一致:
prefix${string}
- 部分一致:
${string}infix${string}
- infixで指定した文字列が先頭や末尾に存在する場合も対象となる
- 後方一致:
${string}suffix
// stringで開始するプロパティを抽出 type Type1 = Pick<Properties, Extract<PropertyKeys, `string${string}`>> // 末尾のeも対象のため、 { string1, string10, string100 } を除いて削除 type Type2 = Omit<Properties, Extract<PropertyKeys, `${string}e${string}`>> // `False` および `false` を抽出 type Type3 = Pick<Properties, Extract<PropertyKeys, `${string}se`>> // 3つ以上 ${string} を書くこともできる // nの後ろに10があるプロパティを抽出 type Type4 = Pick<Properties, Extract<PropertyKeys, `${string}n${string}10${string}`>>
任意の数値での一致
${number}
で、数値のみを指定できる。
// { number1, number10, number100 } を抽出 type Type5 = Pick<Properties, Extract<PropertyKeys, `number${number}`>>
true/falseでの一致
これは使う機会がないと思うが、いちおうできるということで。
${boolean}
で、 true
または false
を指定できる。大文字小文字の区別あり。
// { booleantrue, booleanfalse } を抽出 // { booleanTrue, booleanFalse } は対象外 type Type6 = Pick<Properties, Extract<PropertyKeys, `boolean${boolean}`>>
指定文字列や数値での一致
任意のUnionを指定することで、より細かい判定が可能。
// string または number で始まり、数字 or 'Value' or true で終わるものを抽出 type Type7 = Pick< Properties, Extract<PropertyKeys, `${'string' | 'number'}${number | 'Value' | true}`> >
振り返り
自分の書いたソースをコードレビューしてもらったときに、「これ何やってんの?」と聞かれたので書いてみた。
ただ、けっこう便利なので使っていたが、いつどこで覚えた方法なのか思い出せない。Stack Overflowで引っかけたのか、どこかのブログでも見たのか。
この記事を書くに際し、公式ドキュメントも見てみたが、${string}
が検索しづらく、Template Literal Typesのページ以外見つけられなかった。
何かしら名前がついてそうだが、なんていうんだろう。