Hrvatski

Ovladajte TypeScript pomoćnim tipovima: moćni alati za transformacije tipova, poboljšanje ponovne upotrebljivosti koda i jačanje sigurnosti tipova u vašim aplikacijama.

TypeScript Pomoćni Tipovi: Ugrađeni Alati za Manipulaciju Tipovima

TypeScript je moćan jezik koji donosi statičko tipiziranje u JavaScript. Jedna od njegovih ključnih značajki je sposobnost manipulacije tipovima, što programerima omogućuje stvaranje robusnijeg i lakše održivog koda. TypeScript pruža skup ugrađenih pomoćnih tipova (utility types) koji pojednostavljuju uobičajene transformacije tipova. Ovi pomoćni tipovi su neprocjenjivi alati za jačanje sigurnosti tipova, poboljšanje ponovne upotrebljivosti koda i optimizaciju vašeg razvojnog procesa. Ovaj sveobuhvatni vodič istražuje najbitnije TypeScript pomoćne tipove, pružajući praktične primjere i korisne uvide koji će vam pomoći da ih savladate.

Što su TypeScript Pomoćni Tipovi?

Pomoćni tipovi su unaprijed definirani operatori tipova koji transformiraju postojeće tipove u nove tipove. Ugrađeni su u TypeScript jezik i pružaju sažet i deklarativan način za izvođenje uobičajenih manipulacija tipovima. Korištenje pomoćnih tipova može značajno smanjiti ponavljajući kod (boilerplate) i učiniti vaše definicije tipova izražajnijim i lakšim za razumijevanje.

Zamislite ih kao funkcije koje operiraju na tipovima umjesto na vrijednostima. One uzimaju tip kao ulaz i vraćaju modificirani tip kao izlaz. To vam omogućuje stvaranje složenih odnosa i transformacija tipova s minimalno koda.

Zašto koristiti pomoćne tipove?

Postoji nekoliko uvjerljivih razloga za uključivanje pomoćnih tipova u vaše TypeScript projekte:

Osnovni TypeScript pomoćni tipovi

Istražimo neke od najčešće korištenih i najkorisnijih pomoćnih tipova u TypeScriptu. Pokrit ćemo njihovu svrhu, sintaksu i pružiti praktične primjere kako bismo ilustrirali njihovu upotrebu.

1. Partial<T>

Pomoćni tip Partial<T> čini sva svojstva tipa T opcionalnima. Ovo je korisno kada želite stvoriti novi tip koji ima neka ili sva svojstva postojećeg tipa, ali ne želite zahtijevati da sva budu prisutna.

Sintaksa:

type Partial<T> = { [P in keyof T]?: T[P]; };

Primjer:

interface User {
 id: number;
 name: string;
 email: string;
}

type OptionalUser = Partial<User>; // Sva svojstva su sada opcionalna

const partialUser: OptionalUser = {
 name: "Alice", // Pružamo samo svojstvo imena
};

Slučaj upotrebe: Ažuriranje objekta sa samo određenim svojstvima. Na primjer, zamislite obrazac za ažuriranje korisničkog profila. Ne želite zahtijevati od korisnika da ažuriraju svako polje odjednom.

2. Required<T>

Pomoćni tip Required<T> čini sva svojstva tipa T obaveznima. To je suprotno od Partial<T>. Korisno je kada imate tip s opcionalnim svojstvima i želite osigurati da su sva svojstva prisutna.

Sintaksa:

type Required<T> = { [P in keyof T]-?: T[P]; };

Primjer:

interface Config {
 apiKey?: string;
 apiUrl?: string;
}

type CompleteConfig = Required<Config>; // Sva svojstva su sada obavezna

const config: CompleteConfig = {
 apiKey: "your-api-key",
 apiUrl: "https://example.com/api",
};

Slučaj upotrebe: Osiguravanje da su sve postavke konfiguracije pružene prije pokretanja aplikacije. To može pomoći u sprječavanju grešaka u vremenu izvođenja uzrokovanih nedostajućim ili nedefiniranim postavkama.

3. Readonly<T>

Pomoćni tip Readonly<T> čini sva svojstva tipa T samo za čitanje (readonly). To vas sprječava da slučajno izmijenite svojstva objekta nakon što je stvoren. Ovo promiče nepromjenjivost (immutability) i poboljšava predvidljivost vašeg koda.

Sintaksa:

type Readonly<T> = { readonly [P in keyof T]: T[P]; };

Primjer:

interface Product {
 id: number;
 name: string;
 price: number;
}

type ImmutableProduct = Readonly<Product>; // Sva svojstva su sada samo za čitanje

const product: ImmutableProduct = {
 id: 123,
 name: "Example Product",
 price: 25.99,
};

// product.price = 29.99; // Greška: Nije moguće dodijeliti vrijednost svojstvu 'price' jer je svojstvo samo za čitanje.

Slučaj upotrebe: Stvaranje nepromjenjivih struktura podataka, kao što su konfiguracijski objekti ili objekti za prijenos podataka (DTOs), koji se ne bi trebali mijenjati nakon stvaranja. Ovo je posebno korisno u paradigmama funkcionalnog programiranja.

4. Pick<T, K extends keyof T>

Pomoćni tip Pick<T, K extends keyof T> stvara novi tip odabirom skupa svojstava K iz tipa T. Ovo je korisno kada vam je potreban samo podskup svojstava postojećeg tipa.

Sintaksa:

type Pick<T, K extends keyof T> = { [P in K]: T[P]; };

Primjer:

interface Employee {
 id: number;
 name: string;
 department: string;
salary: number;
}

type EmployeeNameAndDepartment = Pick<Employee, "name" | "department">; // Odabiremo samo ime i odjel

const employeeInfo: EmployeeNameAndDepartment = {
 name: "Bob",
 department: "Engineering",
};

Slučaj upotrebe: Stvaranje specijaliziranih objekata za prijenos podataka (DTO) koji sadrže samo potrebne podatke za određenu operaciju. To može poboljšati performanse i smanjiti količinu podataka koja se prenosi preko mreže. Zamislite slanje detalja o korisniku klijentu, ali isključujući osjetljive informacije poput plaće. Mogli biste koristiti Pick da pošaljete samo `id` i `name`.

5. Omit<T, K extends keyof any>

Pomoćni tip Omit<T, K extends keyof any> stvara novi tip izostavljanjem skupa svojstava K iz tipa T. Ovo je suprotno od Pick<T, K extends keyof T> i korisno je kada želite isključiti određena svojstva iz postojećeg tipa.

Sintaksa:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

Primjer:

interface Event {
 id: number;
 title: string;
description: string;
 date: Date;
 location: string;
}

type EventSummary = Omit<Event, "description" | "location">; // Izostavljamo opis i lokaciju

const eventPreview: EventSummary = {
 id: 1,
 title: "Conference",
 date: new Date(),
};

Slučaj upotrebe: Stvaranje pojednostavljenih verzija modela podataka za specifične svrhe, kao što je prikaz sažetka događaja bez uključivanja punog opisa i lokacije. Ovo se također može koristiti za uklanjanje osjetljivih polja prije slanja podataka klijentu.

6. Exclude<T, U>

Pomoćni tip Exclude<T, U> stvara novi tip isključivanjem iz T svih tipova koji se mogu dodijeliti U. Ovo je korisno kada želite ukloniti određene tipove iz unije tipova (union type).

Sintaksa:

type Exclude<T, U> = T extends U ? never : T;

Primjer:

type AllowedFileTypes = "image" | "video" | "audio" | "document";
type MediaFileTypes = "image" | "video" | "audio";

type DocumentFileTypes = Exclude<AllowedFileTypes, MediaFileTypes>; // "document"

const fileType: DocumentFileTypes = "document";

Slučaj upotrebe: Filtriranje unije tipova kako bi se uklonili specifični tipovi koji nisu relevantni u određenom kontekstu. Na primjer, možda želite isključiti određene vrste datoteka s popisa dopuštenih vrsta datoteka.

7. Extract<T, U>

Pomoćni tip Extract<T, U> stvara novi tip izdvajanjem iz T svih tipova koji se mogu dodijeliti U. Ovo je suprotno od Exclude<T, U> i korisno je kada želite odabrati specifične tipove iz unije tipova.

Sintaksa:

type Extract<T, U> = T extends U ? T : never;

Primjer:

type InputTypes = string | number | boolean | null | undefined;
type PrimitiveTypes = string | number | boolean;

type NonNullablePrimitives = Extract<InputTypes, PrimitiveTypes>; // string | number | boolean

const value: NonNullablePrimitives = "hello";

Slučaj upotrebe: Odabir specifičnih tipova iz unije tipova na temelju određenih kriterija. Na primjer, možda želite izdvojiti sve primitivne tipove iz unije tipova koja uključuje i primitivne tipove i objektne tipove.

8. NonNullable<T>

Pomoćni tip NonNullable<T> stvara novi tip isključivanjem null i undefined iz tipa T. Ovo je korisno kada želite osigurati da tip ne može biti null ili undefined.

Sintaksa:

type NonNullable<T> = T extends null | undefined ? never : T;

Primjer:

type MaybeString = string | null | undefined;

type DefinitelyString = NonNullable<MaybeString>; // string

const message: DefinitelyString = "Hello, world!";

Slučaj upotrebe: Osiguravanje da vrijednost nije null ili undefined prije izvođenja operacije na njoj. To može pomoći u sprječavanju grešaka u vremenu izvođenja uzrokovanih neočekivanim null ili undefined vrijednostima. Razmotrite scenarij u kojem trebate obraditi korisnikovu adresu, a ključno je da adresa nije null prije bilo koje operacije.

9. ReturnType<T extends (...args: any) => any>

Pomoćni tip ReturnType<T extends (...args: any) => any> izdvaja povratni tip funkcijskog tipa T. Ovo je korisno kada želite znati tip vrijednosti koju funkcija vraća.

Sintaksa:

type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;

Primjer:

function fetchData(url: string): Promise<{ data: any }> {
 return fetch(url).then(response => response.json());
}

type FetchDataReturnType = ReturnType<typeof fetchData>; // Promise<{ data: any }>

async function processData(data: FetchDataReturnType) {
 // ...
}

Slučaj upotrebe: Određivanje tipa vrijednosti koju vraća funkcija, posebno kada se radi o asinkronim operacijama ili složenim potpisima funkcija. To vam omogućuje da osigurate ispravno rukovanje vraćenom vrijednošću.

10. Parameters<T extends (...args: any) => any>

Pomoćni tip Parameters<T extends (...args: any) => any> izdvaja tipove parametara funkcijskog tipa T kao n-torku (tuple). Ovo je korisno kada želite znati tipove argumenata koje funkcija prihvaća.

Sintaksa:

type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

Primjer:

function createUser(name: string, age: number, email: string): void {
 // ...
}

type CreateUserParams = Parameters<typeof createUser>; // [string, number, string]

function logUser(...args: CreateUserParams) {
 console.log("Creating user with:", args);
}

Slučaj upotrebe: Određivanje tipova argumenata koje funkcija prihvaća, što može biti korisno za stvaranje generičkih funkcija ili dekoratora koji trebaju raditi s funkcijama različitih potpisa. Pomaže u osiguravanju sigurnosti tipova pri dinamičkom prosljeđivanju argumenata funkciji.

11. ConstructorParameters<T extends abstract new (...args: any) => any>

Pomoćni tip ConstructorParameters<T extends abstract new (...args: any) => any> izdvaja tipove parametara konstruktorske funkcije tipa T kao n-torku (tuple). Ovo je korisno kada želite znati tipove argumenata koje konstruktor prihvaća.

Sintaksa:

type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;

Primjer:

class Logger {
 constructor(public prefix: string, public enabled: boolean) {}
 log(message: string) {
 if (this.enabled) {
 console.log(`${this.prefix}: ${message}`);
 }
 }
}

type LoggerConstructorParams = ConstructorParameters<typeof Logger>; // [string, boolean]

function createLogger(...args: LoggerConstructorParams) {
 return new Logger(...args);
}

Slučaj upotrebe: Slično kao Parameters, ali specifično za konstruktorske funkcije. Pomaže pri stvaranju tvornica (factories) ili sustava za ubrizgavanje ovisnosti (dependency injection) gdje trebate dinamički instancirati klase s različitim potpisima konstruktora.

12. InstanceType<T extends abstract new (...args: any) => any>

Pomoćni tip InstanceType<T extends abstract new (...args: any) => any> izdvaja tip instance konstruktorske funkcije tipa T. Ovo je korisno kada želite znati tip objekta koji konstruktor stvara.

Sintaksa:

type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;

Primjer:

class Greeter {
 greeting: string;
 constructor(message: string) {
 this.greeting = message;
 }
 greet() {
 return "Hello, " + this.greeting;
 }
}

type GreeterInstance = InstanceType<typeof Greeter>; // Greeter

const myGreeter: GreeterInstance = new Greeter("World");
console.log(myGreeter.greet());

Slučaj upotrebe: Određivanje tipa objekta stvorenog od strane konstruktora, što je korisno pri radu s nasljeđivanjem ili polimorfizmom. Pruža tipski siguran način za referenciranje instance klase.

13. Record<K extends keyof any, T>

Pomoćni tip Record<K extends keyof any, T> konstruira objektni tip čiji su ključevi svojstava K, a vrijednosti svojstava T. Ovo je korisno za stvaranje tipova sličnih rječnicima gdje znate ključeve unaprijed.

Sintaksa:

type Record<K extends keyof any, T> = { [P in K]: T; };

Primjer:

type CountryCode = "US" | "CA" | "GB" | "DE";

type CurrencyMap = Record<CountryCode, string>; // { US: string; CA: string; GB: string; DE: string; }

const currencies: CurrencyMap = {
 US: "USD",
 CA: "CAD",
 GB: "GBP",
 DE: "EUR",
};

Slučaj upotrebe: Stvaranje objekata sličnih rječnicima gdje imate fiksni skup ključeva i želite osigurati da svi ključevi imaju vrijednosti određenog tipa. To je uobičajeno pri radu s konfiguracijskim datotekama, mapiranjima podataka ili tablicama za pretraživanje.

Prilagođeni pomoćni tipovi

Iako su ugrađeni pomoćni tipovi u TypeScriptu moćni, možete stvoriti i vlastite prilagođene pomoćne tipove kako biste zadovoljili specifične potrebe u svojim projektima. To vam omogućuje da enkapsulirate složene transformacije tipova i ponovno ih koristite u cijeloj svojoj bazi koda.

Primjer:

// Pomoćni tip za dobivanje ključeva objekta koji imaju specifičan tip
type KeysOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];

interface Person {
 name: string;
 age: number;
 address: string;
 phoneNumber: number;
}

type StringKeys = KeysOfType<Person, string>; // "name" | "address"

Najbolje prakse za korištenje pomoćnih tipova

Zaključak

TypeScript pomoćni tipovi su moćni alati koji mogu značajno poboljšati sigurnost tipova, ponovnu upotrebljivost i održivost vašeg koda. Savladavanjem ovih pomoćnih tipova, možete pisati robusnije i izražajnije TypeScript aplikacije. Ovaj vodič je pokrio najbitnije TypeScript pomoćne tipove, pružajući praktične primjere i korisne uvide koji će vam pomoći da ih uključite u svoje projekte.

Ne zaboravite eksperimentirati s ovim pomoćnim tipovima i istražiti kako se mogu koristiti za rješavanje specifičnih problema u vašem vlastitom kodu. Kako se budete više upoznavali s njima, otkrit ćete da ih sve više koristite za stvaranje čišćih, lakše održivih i sigurnijih TypeScript aplikacija. Bilo da gradite web aplikacije, aplikacije na strani poslužitelja ili bilo što između, pomoćni tipovi pružaju vrijedan set alata za poboljšanje vašeg razvojnog procesa i kvalitete vašeg koda. Iskorištavanjem ovih ugrađenih alata za manipulaciju tipovima, možete otključati puni potencijal TypeScripta i pisati kod koji je istovremeno izražajan i robustan.