tech

テックカテゴリー

TypeScriptの型定義における正規表現ライクなstring型の詳細な定義

Category | front

Tag | TypeScript

Author | naohito-T

Post | 2023-07-30 / 34,254views

こんにちは。

ある要件でセンシティブな文字列を扱う必要があり、TypeScriptが提供しているstring型だけでは要件を満たせない場面がありました。
調べてみると、TypeScriptでは変数の型としてより詳細にstring 型を定義する方法があることを知りましたので、その方法を紹介します。

簡単なコード

まずは簡単なコード紹介です。

先頭にスラッシュを入れなければいけない文字列リテラルを定義したいとき、以下のようにすると実現できます。

const hoge: `/${string}` = '/api'; // エラーが出力されない
const hoge2: `/${string}` = 'api'; // エラーが出力される


TypeScript: TS Playground

また、逆にスラッシュを含めてはいけない場合は、以下のようにinferを使って推測し、neverを返す型を定義することで実現できます。

type NonSlashedString<S extends string> = S extends `/${string}` ? never : S;

const hoge: NonSlashedString<'api'> = 'api'; // エラーが出力されない
const hoge2: NonSlashedString<'/api'> = 'api'; // エラーが出力される
const hoge3: NonSlashedString<'api'> = '/api'; // エラーが出力される


TypeScript: TS Playground

ユースケース紹介(Router定義)

これらの方法を使うと、TypeScriptにおいてstring型をより詳細に定義できます。
特に、センシティブな文字列に対して細かな制約をかける際に役立ちます。
例えば、frontから各APIへ接続する際に、APIパスにスラッシュの有無で挙動が変わってしまう場合があります(例:CORSなど)。

このような文字列のスラッシュ有無などのヒューマンエラーは避けることができない場合もあるため、TypeScriptを使用している以上は静的な型チェックを行いたいと考えることでしょう。

以下のように定義することで、入力値に対して厳密なチェックを行うことができ、安全性を向上させることができます。

type NonSlashedString<S extends string> = S extends `/${string}` ? never : S;
type SlashedString = `/${string}`;

export class Router {
    public static readonly non_slashed: NonSlashedString<'api/public'> = 'api/public';
    public static readonly slashed: SlashedString = '/api/private;
};


TypeScript: TS Playground

NonSlashedStringやSlashedStringなど、型を使って入力値を厳密にチェックすることで、安全性を向上させることができます。
また、型で強制することで他の人が追加する時も安心です。

このように、TypeScriptの型定義における正規表現ライクなstring型の詳細な使い方を紹介しました。
是非、自身のTypeScriptプロジェクトで活用してみてください。

Share this article

naohito-T

naohito-T

千葉出身。都内(銀座)での美容師経験があるソフトウェアエンジニア。モデル撮影のために購入したmacを使っていたらPCの仕組みが気になり始め、気づいたらエンジニアに。人生まるごとクリエイティブだと思っている。人の髪をデザインしていた経験をIT業界へ活かせることはないか日々模索中。