判別式としてのTypescriptテンプレート文字列タイプ

Typescript4.5でテンプレートリテラルタイプを改善

TSの「ナローイング」とは何ですか?

Typescript 4.5以降でのリテラル型の拡張について説明する前に、このコンテキストでの「ナローイング」が実際に何を意味するのかを簡単に要約したいと思います。基本的に、エンティティのプロパティをチェックすることで、Typescriptでタイプを絞り込むことができます。特定のタイプでのみ使用可能なプロパティがエンティティに存在する場合、Typescriptはこれを理解するため、正しいタイプを提供できます。

次のコード例は、それが何を意味するかを示しています。

type Addition = {
    sum: number;
}

type Subtraction = {
    result: number;
}

function calculate(action: Addition | Subtraction) {
    if ('sum' in action) {
      // Simple example of using properties
      // of an entity to narrow down its
      // actual type.
      //
      // 'action' is at this point of type
      // 'Addition'. Nice!
      const addition = action;
    }
}

テンプレート文字列タイプの絞り込み

Typescriptバージョン4.5以降、このパターンはテンプレートリテラルタイプにも適用できます。これは、バッククォート付きの特別な文字列としても知られています。パターンマッチングは、この言語で非常に強力になっています。

もちろん、ナローイングを使用可能にするには、比較のすべてのタイプが同じプロパティキーを共有する必要があります。それ以外の場合は、上記のように一般的なナローイングを簡単に使用できます。

次のコード例は、テンプレート文字列でナローイングを使用する方法を示しています。

type Addition = {
    variant: `${string}-addition`;
    sum: number;
}

type Subtraction = {
    variant: `${string}-subtraction`;
    result: number;
}

function process(action: Addition | Subtraction) {
    if (action.variant === "simple-addition") {
        // Stupid simple example, but you get the idea:
        // We used 'simple-addition', and the pattern 
        // matching by TS understood that '...-addition'
        // can be discriminated to 'Addition'.
        const addition = action;
    }
}
//
// Example that DOES NOT work.
//
// This demo illustrates that the
// discriminante has to be a string,
// else the pattern matching worn't work.

type Addition = {
    variant: `${string}-arithemtic`;
    sum: number;
}

type Subtraction = {
    variant: `${number}-arithemtic`;
    result: number;
}

function process(action: Addition | Subtraction) {
    if (action.variant === "123-arithemtic") {
        // Still 'Addion | Subtraction',
        // as we can only compare against
        // a string '123-arithmetic', which
        // is of course the same for both.
        const addition = action;
    }
}

そして今、あなたはTypescriptでテンプレートリテラルを絞り込むことについて知っています!これはあまり使用しない機能かもしれませんが、適切な場合は、機能がない場合よりもコードの複雑さを大幅に軽減し、コードベースを少しクリーンに保つことができると思います。