V úvodním článku našeho seriálu o TypeScriptu
Efektivní TypeScript jsme se zaměřili na generický transformační typ Partial.
Jeho opakem je Required, ale stejně jako Partial je aplikován pouze na položky na nejvyšší úrovni.
Pojďme si dát tentokrát za cíl vytvoření nového typu z aktuálního tak, že nově vytvořený typ má veškeré položky povinné.
Mějme typový alias User, jehož definice je následující:
type User = {
firstName?: string;
lastName?: string;
age?: number;
}
výsledkem následujícího přiřazení
type RequiredUser = Required<User>;
je typový alias se všemi položkami povinnými.
type User = {
firstName: string;
lastName: string;
age: number;
}
Pro demonstraci toho, že Required označí jako povinné pouze položky na nejvyšší úrovni, si zadefinujme adresu jako
type Address = {
street?: string;
city?: string;
}
a uživatele včetně adresy následovně:
type User = {
firstName?: string;
lastName?: string;
age?: number;
address?: Address;
}
Výsledkem přiřazení
type RequiredUserNoDeep = Required<User>;
pak je
type User = {
firstName: string;
lastName: string;
age: number;
address: {
street?: string;
city?: string;
}
}
Jinými slovy, adresa sama o sobě je povinná, jednotlivé její položky však nikoli.
Pro úplnost se ještě pojďme podívat na implementaci a trochu si ji v krátkosti rozebrat:
type Required = {
[P in keyof T]-?: T[P];
};
Implemetace výše mapuje každou položku původního typu dle daného předpisu. V našem případě je odstraněn z každého klíče původního typu Elvis operátor “?“ a z volitelné položky je učiněna položka povinná.
V porovnání s Partial, probíraném v předešlém článku, a jehož implementace vykonává pravý opak, každý klíč původního typu označuje jako volitelný.
type Partial = {
[P in keyof T]?: T[P];
};
Je dobré si pamatovat, že pokud použijeme typ Required v projektu, kde TypeScriptový překladač má nastavenu hodnotu strictNullChecks: true, pak aplikace typu Required neodstraní pouze nepovinnost dané položky, ale též undefined. Pojďme si to ukázat na příkladu, definujme uživatele následovně:
type User = {
firstName: string;
lastName?: string;
thirdName?: string | undefined;
age: number;
}
a proveďme následující přiřazení:
type RequiredUser = Required<User>;
pak výsledný alias vypadá takto:
type Required<User> = {
firstName: string;
lastName: string;
thirdName: string;
age: number;
}
jinými slovy, při použití původního typu User jsme byli schopni uložit hodnotu undefined do proměnných lastName a thirdName
let user: User = {
firstName: 'Adam',
lastName: undefined,
thirdName: undefined,
age: 30
}
zatímco po aplikaci Required již hodnotu undefined vložit do proměnných lastName a thirdName není povoleno a následující kód skončí chybou. Ušetřete si práce a mějte toto chování na paměti.
let user: Required<User> = {
firstName: 'Adam',
lastName: undefined,
thirdName: undefined,
age: 30
}
Závěrem
Tentokrát jsme si ukázali, jak se standardně Required chová a také jsme se seznámili se situací, jak se jeho chování změní, když je parametr strictNullChecks nastaven na hodnotu true. Příště se zaměříme na Capitalize a Uncapitalize.
Václav Kandus