Typescript 4.9 ha aggiunto l'operatore satisfies
, che permette di vincolare l'assegnazione a valori che soddisfano un certo tipo. Ad esempio:
// se scegliamo "string", possiamo usare solo valori che sono stringhe
const myVar1 = "hello" satisfies string;
const myVar2 = 42 satisfies string; // errore, 42 non è una stringa
// anche definendo la costante di tipo string forziamo lo stesso
// comportamento
const myVar3: string = "hello";
Ma allora cosa cambia? L'utilità di satisfies
è che permette di restringere i valori assegnabili senza "allargare/cambiare" il tipo della variabile risultante. In altri termini:
const myHello = "hello" as const; // tipo "hello" non string
const myVar1 = myHello satisfies string;
// myVar1 è di tipo "hello", quindi più preciso, e non string
// ma in più sappiamo che ci vincoliamo ad assegnargli una string
// e non altri valori
Un caso reale (ipotizzando tsconfig option "strict"=true):
// voglio modellare le variabili d'ambiente per la connessione a db
type EnvironmentVariableName = "DB_HOST" | "DB_PASSWORD";
// voglio costruire un oggetto con un valore di default per ogni
// variabile d'ambiente
const values1 = {
DB_HOST: "host",
DB_PASSWORD: "password",
};
// come fare a tipizzarlo affinché abbia solo le chiavi con i nomi
// delle variabili d'ambiente?
const values2: Record<EnvironmentVariableName, string> = {
DB_HOST: "host",
DB_PASSWORD: "password",
};
// ora l'oggetto è correttamente tipizzato, ma cosa succede se non
// abbiamo un default per una delle chiavi?
const values3: Record<EnvironmentVariableName, string> = {
DB_HOST: "host",
DB_PASSWORD: undefined,
}; // -> errore, non possiamo assegnare undefined a string
// prima soluzione: far si che le chiavi possano essere undefined
const values4: Record<EnvironmentVariableName, string | undefined> = {
DB_HOST: "host",
DB_PASSWORD: undefined,
};
// ora però quando accedo a una qualsiasi chiave, anche quelle per cui
// ho indicato un valore ottengo un qualcosa di potenzialmente
// undefined
console.log(values4.DB_HOST);
// string | undefined, anche se abbiamo usato il valore "host"
// soluzione con satisfies
const values5 = {
DB_HOST: "host",
DB_PASSWORD: undefined,
} satisfies Record<EnvironmentVariableName, string | undefined>;
// in questo modo il type system ci forzerà ad assegnare un valore
// compatibile con i nostri requisiti mentre il valore delle singole
// chiavi sarà precisamente come l'abbiamo valorizzato
console.log(values5.DB_HOST); // string, "host"
console.log(values5.DB_PASSWORD); // undefined
Per un altro ottimo esempio si rimanda all'articolo ufficiale di annuncio del nuovo operatore in typescript 4.9.
Kristian Notari
article.cta.title
If you are looking for support for decision-making, problem-solving and strategy optimization or for the development of solutions and software suitable for your company, you have found it. Contact the Orangeloop specialized team now to bring your projects to life.