Efektivní TypeScript
05.01.2022
Efektivní TypeScript

​TypeScript je velmi populární oop jazyk, jenž staví na JavaScriptu a poskytuje vývojářům mnohem širší spektrum technik v programování. První rozdíl, kterého si všimneme na první pohled, je silná typovost, která se v JavaScriptu nevyskytuje a umožňuje nám deklarovat typ parametrů, proměnných či návratových hodnot, jenž očekáváme, a případné chyby se dají odhalit již v době kompilace nikoli v „run time“ jako v případě JavaScriptu. Rozdílů mezi TypeSriptem a JavaScriptem je však více - například TypeScript oproti JavaScriptu musí být kompilován,  má podporu generik, volitelnost parametrů atd. Díky tomu je kód bezpečnější, robustnější a lépe udržovatelný.

V Cleverlance je jeho používání denním chlebem, píšeme v něm velké množství webových aplikací. Díky  svým rysům umožňuje psát efektivní, udržovatelný a abstraktní kód. Projekty, které řešíme za použití TypeScriptu i ve spojení s jinými knihovnami či frameworky, sahají od menších aplikací až po core systémy bank a pojišťoven.

Rozhodli jsme se, že se o své zkušenosti podělíme, a připravili jsme si pro vás seriál na tipy a triky používané při vývoji v TypeScriptu, který pro vás budeme na tomto blogu pravidelně na měsíční bázi zveřejňovat.

Jak víte, Utility types jsou vestavěné generické mapované typy, které nám usnadňují vytváření nových typů z již existujících tak, aby splňovaly naše požadavky, a jejichž deklarace můžeme naleznout například v lib.es5.d.ts či lib.es6.d.ts v závislosti na použité verzi jazyka. Kýženého výsledku je dosaženo voláním transformační metody nad původním datovým typem a využívaní funkcionalit, mezi které patří například keyof, typeof, indexace. Využívání těchto předdefinovaných typů nám umožňuje psát lépe čitelný a udržovatelný kód s menším množstvím chyb.

Mezi nabízené utility typy patří

  • Partial<Type>
  • Required<Type>
  • Readonly<Type>
  • Record<Keys, Type>
  • Pick<Type, Keys>
  • Omit<Type, Keys>
  • Exclude<Type, ExcludedUnion>
  • Extract<Type, Union>
  • NonNullable<Type>
  • Parameters<Type>
  • ConstructorParameters<Type>
  • ReturnType<Type>
  • InstanceType<Type>
  • ThisParameterType<Type>
  • OmitThisParameter<Type>
  • ThisType<Type>
  • Intrinsic String Manipulation Types
  • Uppercase<StringType>
  • Lowercase<StringType>
  • Capitalize<StringType>
  • Uncapitalize<StringType>

Pojďme společně postupně rozebrat jednotlivě nabízené možnosti a ukázat si také, jak naimplementovat vlastní typovou transformaci. V prvním díle našeho seriálu se budeme konkrétně věnovat  Partial<Type>.

Dáme si za cíl vytvoření nového typu z aktuálního tak, že nově vytvořený typ má veškeré položky volitelné.

Pokud chceme deklarovat položku rozhraní či parametr metody jako volitelný, tak pro tento účel použijeme Elvis operátor "?​" za názvem dané položky. Tento způsob deklarace je poněkud zdlouhavý a náchylný k chybám, jestliže chceme deklarovat veškeré položky rozhraní či třídy jako volitelné. V tento moment nám přijde vhod generický transformační typ Partial<Type>​, který můžeme naleznout například v lib.es5.d.ts. Podívejme se, jak tento typ funguje.

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 PartialUser = Partial​<U​ser​>; je typový alias se všemi položkami označenými jako volitelné.

   
   type User = {
  firstName?: string;
  lastName?: string;
  age?: number;
}

Pro demonstraci toho, že Partial<Type> označí jako volitelné 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 následujícího přiřazení type PartialUserNoDeep = Partial<User>; pak je

   
   type User = {
  firstName?: string;
  lastName?: string;
  age?: number;
  address?: {
    street: string;
    city: string;
  }
}

Jinými slovy - adresa sama o sobě je volitelná, pokud se ji však rozhodneme použít, tak musíme dodržet její rozhraní.

Pro úplnost ještě uvedeme implementaci

   
   type Partial = {
  [P inkeyof T]?: T[P];
};

Kde se dá tahle vychytávka použít?

  • Běžným případem je “update pattern", který můžeme například naleznout v knihovnách řešící state management a kde chceme zapsat jen určitou podmnožinu informací.
  • Dalším je případ, kdy nemáme nebo nechceme předávat celou strukturu, ale jen předat data, jež nás zajímají.
  • Deklarování parametrického konstruktoru s výchozími hodnotami.

 

Závěrem

V článku jsme chtěli ukázat, jak se výše zmíněný typ chová, jak jej použít a na co si dát pozor, zvláště na vlastnost, kdy jsou označovány jako volitelné položky pouze ty, jenž jsou umístěny na nejvyšší úrovni.
Doufáme, že vás téma zaujalo. Mějte se, za měsíc se potkáme znovu a společně probereme téma týkající se Required<Type>.

Václav Kandus