Stringhe modello con tag dattiloscritto

Come utilizzare le stringhe modello come funzioni

Le basi: stringhe modello

Prima di parlare di stringhe modello con tag, chiamate anche letterali modello, voglio solo dare una rapida introduzione alle stringhe modello in generale. Sentiti libero di passare al prossimo capitolo se sai già di cosa si tratta.

Le stringhe modello sono un tipo speciale di simboli di stringa che possono contenere espressioni Javascript e si estendono su più righe. Usano i caratteri backtick invece delle doppie virgolette, come nel caso delle stringhe comuni.

Per quanto riguarda l'estensione dei caratteri su più righe, una stringa comune deve contenere una barra rovesciata in combinazione con il carattere "n" per creare una nuova riga. Con le stringhe modello, puoi semplicemente creare una nuova riga "in linea", per così dire.

// A common string as reference.
const string = "I'm just a string";

// A template string. For Typescript,
// this value is a plain 'string'-type.
const templateString = `I'm just a string as well`;

Anche la disponibilità di espressioni all'interno di una stringa può essere spiegata rapidamente. Invece di consentire solo simboli di stringa, le stringhe modello accettano espressioni arbitrarie. L'esempio seguente mostra cosa intendo con questo.

function greet(name: string) {
  // Here you see an expression
  // *embedded* inside a string.
  return `Hello, ${name}!`;
}

// "Hello, Tom!"
const greeting = greet("Tom");

// One more example, using
// Typescript's 'rest'-operator
// which allowes any number of values
// and provides them as an array,
// in our case of type 'string'.
function greetAll(...names: string[]) {
  return `Hi everybody: ${names.join(", ")}!`;
}

// "Hi everybody: Tom, Luke!"
const greetingForAll = greetAll("Tom", "Luke");

Stringhe modello con tag

Questo insieme di funzionalità da solo sarebbe già bello, ma le stringhe di modello possono essere utilizzate anche come funzioni. Metti semplicemente una parola chiave davanti alla stringa del modello per "taggarla", da cui il nome "stringhe del modello con tag". È ora del prossimo esempio.

// All previous examples used 'untagged'
// string literals, which means they're 
// practially just a string.
//
// But let's see how we can convert them
// to an acutal function:
function merge(template: TemplateStringsArray, ...params: string[]){
  
  // This needs some explanation:
  //
  // 'template', our first param, contains
  // all strings *inbetween the paramters*,
  // you'll see in a minute what I mean by that.
  //
  // 'params' then is an array of strings
  // that were provided as paramteres to the
  // template string.
  
  // Let's ignore the result for now.
  return "";
}

const what = "test";

// Here's the tagged template string in action.
// The tag is the function name, and like a 
// function the tagged template string can be called.
//
// Let's destruct how this will look like
// in the function defined above.
//
// 'template' = ["Just a", ""];
// 'params'   = ["test"]
const result = merge`Just a ${what}`;

// As you can see, the function splits the string
// into the string-only parts and the expressions.

Come puoi vedere, la sintassi sembra piuttosto interessante e forse anche un po' estranea quando ci lavori per la prima volta. Probabilmente non ci sono molti casi d'uso che richiedono l'implementazione di stringhe modello con tag, ma comunque possiamo giocarci. Nel seguente e ultimo esempio, ho messo insieme alcuni casi di studio. Come vedrai, le stringhe di modello con tag possono essere utilizzate naturalmente con i generici e aprire alcune opzioni interessanti per l'implementazione di determinati requisiti.

// 
// Generic
//
// Tagged template literals can be generic, too.
function generic<T>(template: TemplateStringsArray, ...params: T[]){
    return template.join(",") + params.join(",")
}

// "A value: ,test"
console.log(generic<string>`A value: ${"test"}`);

//
// Generic (with super powers)
//
// You can specify each type and 
// also limit the number of params!
function coalesce<A, B, C>(template: TemplateStringsArray, ...params: [A, B, C]){
    return template.join(",") + params.join(",")
}

// ", - , - ,value,0,true" 
const res = coalesce<string, number, boolean>`${"value"} - ${0} - ${true}`;

//
// Different return type
//
// Also, tagged literal types don't 
// only have to return strings.
const preview = (template: TemplateStringsArray, ...params: number[]) 
  => (template2: TemplateStringsArray, ...params2: string[])
  => {
    return "what?";
}

// Note the two pairs of backticks
// after each other, we're just calling
// the returned tagged template string
// form our first one!
console.log(preview`${0}``${"a"}`);

Spero che ti sia piaciuto questo viaggio sul campo piuttosto veloce in una delle funzionalità di Javascript e Typescript. Le stringhe di modello sono molto probabilmente una cosa comune nella tua base di codice, le stringhe di modello con tag probabilmente no, quindi è interessante saperne di più su tali funzionalità di nicchia.

Suggerimenti

Correlati

Addendum

Lingue