TypeScript正規表現型定義
TypeScript では、正規表現にマッチする文字列型を直接定義することはできません。しかし、いくつかの技法を使って、ある程度この目的を達成することができます。
テンプレートリテラル型とブランド付け
この手法では、テンプレートリテラル型とブランド付けを使って、特定の正規表現パターンにマッチする文字列型を定義します。
type EmailRegex = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
type Email = `${string & { __brand: EmailRegex }}`;
function sendEmail(email: Email) {
// ...
}
sendEmail('[email protected]'); // 正しい
sendEmail('invalid_email'); // エラー
ここで、EmailRegex
は正規表現パターンを定義しています。Email
型は、このパターンにマッチする文字列のみを受け付けます。
型アサーションと関数
この手法では、関数を定義し、その引数に正規表現パターンを指定します。関数の内部で、入力文字列がパターンにマッチすることを確認し、型アサーションを使って、マッチする文字列型を返します。
function isEmail(email: string): email is Email {
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(email);
}
const email: Email = '[email protected]';
if (isEmail(email)) {
// email は Email 型として扱われる
}
テンプレートリテラル型のみ
この手法は、ブランド付けを使わずに、テンプレートリテラル型のみを使って、正規表現パターンを直接指定します。
type Email = `${string & { __brand: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/ }}`;
注意
- TypeScript の今後のバージョンでは、正規表現にマッチする文字列型の直接的なサポートが追加される可能性があります。
- より複雑な正規表現パターンや、複数の正規表現パターンを組み合わせる場合は、カスタム型ガード関数やユーティリティ型を定義する必要があるかもしれません。
- これらの手法は、コンパイル時の型チェックを強化するのに役立ちますが、実行時の検証は必要です。
type EmailRegex = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
type Email = `${string & { __brand: EmailRegex }}`;
function sendEmail(email: Email) {
// ...
}
sendEmail('[email protected]'); // 正しい
sendEmail('invalid_email'); // エラー
__brand
プロパティは、ブランド付けと呼ばれる手法で、型を区別するためのものです。Email
型は、このパターンにマッチする文字列のみを受け付けます。EmailRegex
は正規表現パターンを定義します。
function isEmail(email: string): email is Email {
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(email);
}
const email: Email = '[email protected]';
if (isEmail(email)) {
// email は Email 型として扱われる
}
- マッチした場合、型アサーション
email is Email
を使って、その変数をEmail
型として扱えるようにします。 isEmail
関数は、入力された文字列がEmailRegex
にマッチするかを検証します。
type Email = `${string & { __brand: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/ }}`;
- この手法は、ブランド付けのみを使って、正規表現パターンを直接指定します。
カスタム型ガード関数を使って、正規表現パターンにマッチするかどうかを検証し、マッチした場合に特定の型を返します。
function isEmail(str: string): str is Email {
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
}
ユーティリティ型
ユーティリティ型を使って、より柔軟な正規表現パターンマッチングを実現します。
type RegexMatch<T extends string, R extends RegExp> = T extends `${infer U}${R}${infer V}` ? U & V : never;
type Email = RegexMatch<string, /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/>;
第三者ライブラリ
サードパーティのライブラリを利用することで、より強力な正規表現パターンマッチング機能を提供します。例えば、io-ts
ライブラリを使用すると、以下のように定義できます。
import * as t from 'io-ts';
const Email = t.regexp(/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/);
- 正規表現パターンは正確かつ適切に定義することが重要です。誤ったパターンは、意図しない結果やセキュリティリスクにつながる可能性があります。
- 適切な手法を選択する際には、プロジェクトの規模、複雑さ、およびチームのスキルレベルを考慮してください。
- これらの手法は、コンパイル時の型チェックを強化し、コードの安全性と信頼性を向上させるのに役立ちます。
regex typescript types