TypeScript er blevet industristandarden for storstilet webudvikling. Mens de fleste udviklere kender det grundlæggende om interfaces og typer, ligger den virkelige kraft i dets avancerede typesystem. Her er 5 mønstre, der vil adskille dig som seniorudvikler.
1. Generic Constraints
Generics er kraftfulde, men nogle gange har du brug for at begrænse, hvad der kan sendes ind. extends er din ven her.
interface HasId { id: string; } function getById<T extends HasId>(list: T[], id: string): T | undefined { return list.find((item) => item.id === id); }
Ved at sikre, at T udvider HasId, garanterer vi, at det er sikkert at tilgå .id inde i funktionen.
2. Conditional Types
Conditional Types giver dig mulighed for at oprette ikke-uniforme typemappings. Syntaksen ligner den ternære operator i JavaScript.
type IsString<T> = T extends string ? true : false; type A = IsString<string>; // true type B = IsString<number>; // false
Et praktisk anvendelsestilfælde er at filtrere typer fra en union:
type Diff<T, U> = T extends U ? never : T; type NonNullable<T> = Diff<T, null | undefined>;
3. Mapped Types
Mapped Types giver dig mulighed for at oprette nye typer baseret på gamle ved at transformere egenskaber.
type ReadOnly<T> = { readonly [P in keyof T]: T[P]; }; interface User { name: string; age: number; } type ReadOnlyUser = ReadOnly<User>;
Du kan endda tilføje eller fjerne modifikatorer:
type Mutable<T> = { -readonly [P in keyof T]: T[P]; };
4. Template Literal Types
Introduceret i TypeScript 4.1 giver disse dig mulighed for at manipulere strengtyper direkte.
type World = 'world'; type Greeting = `hello ${World}`; // "hello world" type Color = 'red' | 'blue'; type Quantity = 'light' | 'dark'; type Palette = `${Quantity}-${Color}`; // "light-red" | "light-blue" | "dark-red" | "dark-blue"
Dette er utroligt nyttigt til at type strenge, der følger et bestemt mønster, som CSS-klasser eller hændelsesnavne.
5. Nøgleordet infer
Nøgleordet infer inden for conditional types giver dig mulighed for at udtrække typer fra andre typer.
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any; function check(): boolean { return true; } type CheckReturn = ReturnType<typeof check>; // boolean
Her beder vi TypeScript om at "udlede" returtypen R af en funktion og returnere den.
Konklusion
At mestre disse mønstre giver dig mulighed for at skrive biblioteker og værktøjer, der er robuste og giver en fremragende udvikleroplevelse (DX). Målet med avanceret TypeScript er ikke kompleksitet for kompleksitetens skyld, men sikkerhed og udtryksfuldhed.