Tipi di stringhe modello dattiloscritti come discriminanti

Tipi letterali modello migliorati con Typescript 4.5

Che cos'è "Restringimento" in TS?

Prima di dare un'occhiata al miglioramento dei tipi letterali in Typescript 4.5 e versioni successive, voglio solo ricapitolare rapidamente cosa significa effettivamente "Restringimento" in questo contesto. Fondamentalmente puoi restringere un tipo in Typescript controllando le proprietà dell'entità. Se esiste una proprietà sull'entità che è disponibile solo per un determinato tipo, Typescript lo comprende e può quindi fornire i tipi corretti.

Il seguente esempio di codice dimostra cosa intendo con questo.

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

Restringimento per i tipi di stringhe modello

A partire dalla versione 4.5 di Typescript, questo modello può essere applicato anche ai tipi letterali modello, noti anche come stringhe speciali con apici inversi. Il pattern matching sta diventando davvero potente nella lingua.

Ovviamente, affinché il restringimento diventi utilizzabile, tutti i tipi nel confronto devono condividere la stessa chiave di proprietà. Altrimenti, puoi semplicemente usare il restringimento comune come sopra.

L'esempio di codice seguente mostra come le stringhe modello possono utilizzare il restringimento:

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

E ora sai come restringere i valori letterali del modello in Typescript! Questa potrebbe essere una funzionalità che non utilizzerai molto spesso, ma quando è appropriato, penso che possa ridurre notevolmente la complessità del codice e mantenere la tua base di codice un po' più pulita che senza la funzionalità.