Types de chaîne de modèle de script dactylographié en tant que discriminants

Types de littéraux de modèle améliorés avec Typescript 4.5

Qu'est-ce que le « rétrécissement » dans TS ?

Avant de jeter un coup d'œil à l'amélioration des types littéraux dans Typescript 4.5 et versions ultérieures, je souhaite simplement récapituler rapidement ce que signifie réellement « rétrécir » dans ce contexte. Fondamentalement, vous pouvez affiner un type dans Typescript en vérifiant les propriétés de l'entité. S'il existe une propriété sur l'entité qui n'est disponible que pour un certain type, alors Typescript le comprend et peut donc fournir les types corrects.

L'exemple de code suivant montre ce que je veux dire par là.

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;
    }
}

Restriction pour les types de chaîne de modèle

À partir de Typescript version 4.5, ce modèle peut également être appliqué pour les types de littéraux de modèle, également connus sous le nom de chaînes spéciales avec des backticks. Le pattern matching devient vraiment puissant dans le langage.

Bien entendu, pour que le rétrécissement devienne utilisable, tous les types de la comparaison doivent partager la même clé de propriété. Sinon, vous pouvez simplement utiliser le rétrécissement commun comme ci-dessus.

L'exemple de code suivant montre comment les chaînes de modèle peuvent utiliser le rétrécissement :

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;
    }
}

Et maintenant, vous savez comment réduire les littéraux de modèle dans Typescript ! C'est peut-être une fonctionnalité que vous n'utiliserez pas très souvent, mais lorsque cela est approprié, je pense que cela peut réduire considérablement la complexité du code et garder votre base de code un peu plus propre que sans la fonctionnalité.