Ovladajte pozivima API-ja sigurni za tip u TypeScriptu za robusne, održive i web aplikacije bez grešaka. Naučite najbolje prakse i napredne tehnike.
Pozivi API-ja sigurni za tip u TypeScriptu: Sveobuhvatan vodič
U modernom web razvoju, interakcija s API-jima je temeljan zadatak. TypeScript, sa svojim snažnim sustavom tipova, nudi značajnu prednost u osiguravanju pouzdanosti i održivosti vaših aplikacija omogućavanjem poziva API-ja sigurnih za tip. Ovaj će vodič istražiti kako iskoristiti značajke TypeScripta za izgradnju robusnih interakcija s API-jem bez grešaka, pokrivajući najbolje prakse, napredne tehnike i primjere iz stvarnog svijeta.
Zašto je sigurnost tipa važna za pozive API-ja
Kada radite s API-jima, u osnovi se bavite podacima koji dolaze iz vanjskog izvora. Ti podaci možda neće uvijek biti u formatu koji očekujete, što dovodi do pogrešaka tijekom izvođenja i neočekivanog ponašanja. Sigurnost tipa pruža ključni sloj zaštite provjerom da se podaci koje primate pridržavaju unaprijed definirane strukture, hvatajući potencijalne probleme rano u procesu razvoja.
- Smanjene pogreške tijekom izvođenja: Provjera tipa u vrijeme kompajliranja pomaže identificirati i ispraviti pogreške povezane s tipovima prije nego što dođu do produkcije.
- Poboljšana održivost koda: Jasne definicije tipova čine vaš kod lakšim za razumijevanje i izmjenu, smanjujući rizik od unošenja grešaka tijekom refaktoriranja.
- Poboljšana čitljivost koda: Napomene tipova pružaju vrijednu dokumentaciju, olakšavajući programerima razumijevanje očekivanih struktura podataka.
- Bolje iskustvo za razvojne programere: IDE podrška za provjeru tipa i automatsko dovršavanje značajno poboljšava iskustvo razvojnih programera i smanjuje vjerojatnost pogrešaka.
Postavljanje vašeg TypeScript projekta
Prije nego što se upustite u pozive API-ja, provjerite jeste li postavili TypeScript projekt. Ako počinjete ispočetka, možete inicijalizirati novi projekt koristeći:
npm init -y
npm install typescript --save-dev
tsc --init
To će stvoriti datoteku `tsconfig.json` s zadanim opcijama TypeScript kompilatora. Ove opcije možete prilagoditi kako bi odgovarale potrebama vašeg projekta. Na primjer, možda ćete htjeti omogućiti strogi način rada za strožu provjeru tipa:
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Definiranje tipova za API odgovore
Prvi korak u postizanju poziva API-ja sigurnih za tip je definiranje TypeScript tipova koji predstavljaju strukturu podataka koju očekujete primiti od API-ja. To se obično radi pomoću deklaracija `interface` ili `type`.
Korištenje sučelja
Sučelja su moćan način za definiranje oblika objekta. Na primjer, ako dohvaćate popis korisnika iz API-ja, možda ćete definirati sučelje poput ovog:
interface User {
id: number;
name: string;
email: string;
address?: string; // Opcionalno svojstvo
phone?: string; // Opcionalno svojstvo
website?: string; // Opcionalno svojstvo
company?: {
name: string;
catchPhrase: string;
bs: string;
};
}
`?` iza naziva svojstva označava da je svojstvo opcionalno. To je korisno za rukovanje API odgovorima gdje određena polja mogu nedostajati.
Korištenje tipova
Tipovi su slični sučeljima, ali nude veću fleksibilnost, uključujući mogućnost definiranja unijskih tipova i tipova presjeka. Možete postići isti rezultat kao i gornje sučelje pomoću tipa:
type User = {
id: number;
name: string;
email: string;
address?: string; // Opcionalno svojstvo
phone?: string; // Opcionalno svojstvo
website?: string; // Opcionalno svojstvo
company?: {
name: string;
catchPhrase: string;
bs: string;
};
};
Za jednostavne strukture objekata, sučelja i tipovi su često zamjenjivi. Međutim, tipovi postaju moćniji kada se radi sa složenijim scenarijima.
Uspostavljanje API poziva s Axiosom
Axios je popularni HTTP klijent za upućivanje API zahtjeva u JavaScriptu i TypeScriptu. Pruža čisti i intuitivni API, olakšavajući rukovanje različitim HTTP metodama, zaglavljima zahtjeva i podacima odgovora.
Instaliranje Axiosa
npm install axios
Uspostavljanje poziva API-ja s tipom
Da biste uspostavili poziv API-ja siguran za tip s Axiosom, možete koristiti metodu `axios.get` i odrediti očekivani tip odgovora pomoću generičkih tipova:
import axios from 'axios';
async function fetchUsers(): Promise<User[]> {
try {
const response = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
return response.data;
} catch (error) {
console.error('Greška pri dohvaćanju korisnika:', error);
throw error;
}
}
fetchUsers().then(users => {
users.forEach(user => {
console.log(user.name);
});
});
U ovom primjeru, `axios.get<User[]>('...')` govori TypeScriptu da se očekuje da će podaci odgovora biti niz objekata `User`. To omogućuje TypeScriptu provjeru tipa i automatsko dovršavanje prilikom rada s podacima odgovora.
Rukovanje različitim HTTP metodama
Axios podržava razne HTTP metode, uključujući `GET`, `POST`, `PUT`, `DELETE` i `PATCH`. Možete koristiti odgovarajuće metode za uspostavljanje različitih vrsta API zahtjeva. Na primjer, za stvaranje novog korisnika, možete koristiti metodu `axios.post`:
async function createUser(user: Omit<User, 'id'>): Promise<User> {
try {
const response = await axios.post<User>('https://jsonplaceholder.typicode.com/users', user);
return response.data;
} catch (error) {
console.error('Greška pri stvaranju korisnika:', error);
throw error;
}
}
const newUser = {
name: 'John Doe',
email: 'john.doe@example.com',
address: '123 Main St',
phone: '555-1234',
website: 'example.com',
company: {
name: 'Example Corp',
catchPhrase: 'Leading the way',
bs: 'Innovative solutions'
}
};
createUser(newUser).then(user => {
console.log('Kreirani korisnik:', user);
});
U ovom primjeru, `Omit<User, 'id'>` stvara tip koji je isti kao `User`, ali bez svojstva `id`. To je korisno jer `id` obično generira poslužitelj prilikom stvaranja novog korisnika.
Korištenje Fetch API-ja
Fetch API je ugrađeni JavaScript API za upućivanje HTTP zahtjeva. Iako je osnovniji od Axiosa, također se može koristiti s TypeScriptom za postizanje poziva API-ja sigurnih za tip. Možda ga više volite kako biste izbjegli dodavanje ovisnosti ako odgovara vašim potrebama.
Uspostavljanje poziva API-ja s tipom pomoću Fetcha
Da biste uspostavili poziv API-ja siguran za tip s Fetchom, možete koristiti funkciju `fetch`, a zatim raščlaniti odgovor kao JSON, navodeći očekivani tip odgovora:
async function fetchUsers(): Promise<User[]> {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error(`HTTP greška! status: ${response.status}`);
}
const data: User[] = await response.json();
return data;
} catch (error) {
console.error('Greška pri dohvaćanju korisnika:', error);
throw error;
}
}
fetchUsers().then(users => {
users.forEach(user => {
console.log(user.name);
});
});
U ovom primjeru, `const data: User[] = await response.json();` govori TypeScriptu da se s podacima odgovora treba postupati kao s nizom objekata `User`. To omogućuje TypeScriptu provjeru tipa i automatsko dovršavanje.
Rukovanje različitim HTTP metodama s Fetchom
Da biste uspostavili različite vrste API zahtjeva s Fetchom, možete koristiti funkciju `fetch` s različitim opcijama, kao što su opcije `method` i `body`. Na primjer, da biste stvorili novog korisnika, možete koristiti sljedeći kod:
async function createUser(user: Omit<User, 'id'>): Promise<User> {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
});
if (!response.ok) {
throw new Error(`HTTP greška! status: ${response.status}`);
}
const data: User = await response.json();
return data;
} catch (error) {
console.error('Greška pri stvaranju korisnika:', error);
throw error;
}
}
const newUser = {
name: 'John Doe',
email: 'john.doe@example.com',
address: '123 Main St',
phone: '555-1234',
website: 'example.com',
company: {
name: 'Example Corp',
catchPhrase: 'Leading the way',
bs: 'Innovative solutions'
}
};
createUser(newUser).then(user => {
console.log('Kreirani korisnik:', user);
});
Rukovanje API pogreškama
Rukovanje pogreškama ključni je aspekt API poziva. API-ji mogu propasti iz mnogo razloga, uključujući probleme s mrežnom vezom, pogreške poslužitelja i nevažeće zahtjeve. Bitno je graciozno rukovati ovim pogreškama kako biste spriječili pad vaše aplikacije ili prikazivanje neočekivanog ponašanja.
Korištenje blokova Try-Catch
Najčešći način rukovanja pogreškama u asinkronom kodu je korištenje blokova try-catch. To vam omogućuje da uhvatite sve iznimke koje se bacaju tijekom API poziva i da im prikladno rukujete.
async function fetchUsers(): Promise<User[]> {
try {
const response = await axios.get<User[]>('https://jsonplaceholder.typicode.com/users');
return response.data;
} catch (error) {
console.error('Greška pri dohvaćanju korisnika:', error);
// Obradite pogrešku, npr. prikažite poruku o pogrešci korisniku
throw error; // Ponovno bacite pogrešku kako biste omogućili kodu koji poziva da je također obradi
}
}
Rukovanje specifičnim kodovima pogrešaka
API-ji često vraćaju specifične kodove pogrešaka kako bi ukazali na vrstu pogreške koja se dogodila. Možete koristiti ove kodove pogrešaka za pružanje specifičnijeg rukovanja pogreškama. Na primjer, možda ćete htjeti prikazati drugačiju poruku o pogrešci za pogrešku 404 Not Found nego za pogrešku 500 Internal Server Error.
async function fetchUser(id: number): Promise<User | null> {
try {
const response = await axios.get<User>(`https://jsonplaceholder.typicode.com/users/${id}`);
return response.data;
} catch (error: any) {
if (error.response?.status === 404) {
console.log(`Korisnik s ID-om ${id} nije pronađen.`);
return null; // Ili bacite prilagođenu pogrešku
} else {
console.error('Greška pri dohvaćanju korisnika:', error);
throw error;
}
}
}
fetchUser(123).then(user => {
if (user) {
console.log('Korisnik:', user);
} else {
console.log('Korisnik nije pronađen.');
}
});
Stvaranje prilagođenih tipova pogrešaka
Za složenije scenarije rukovanja pogreškama, možete stvoriti prilagođene tipove pogrešaka koji predstavljaju različite vrste API pogrešaka. To vam omogućuje da pružite strukturiranije informacije o pogreškama i učinkovitije rukujete pogreškama.
class ApiError extends Error {
constructor(public statusCode: number, message: string) {
super(message);
this.name = 'ApiError';
}
}
async function fetchUser(id: number): Promise<User> {
try {
const response = await axios.get<User>(`https://jsonplaceholder.typicode.com/users/${id}`);
return response.data;
} catch (error: any) {
if (error.response?.status === 404) {
throw new ApiError(404, `Korisnik s ID-om ${id} nije pronađen.`);
} else {
console.error('Greška pri dohvaćanju korisnika:', error);
throw new ApiError(500, 'Internal Server Error'); // Ili bilo koji drugi odgovarajući kod statusa
}
}
}
fetchUser(123).catch(error => {
if (error instanceof ApiError) {
console.error(`API Greška: ${error.statusCode} - ${error.message}`);
} else {
console.error('Došlo je do neočekivane pogreške:', error);
}
});
Validacija podataka
Čak i sa sustavom tipova TypeScripta, ključno je validirati podatke koje primate od API-ja tijekom izvođenja. API-ji mogu promijeniti strukturu odgovora bez obavijesti, a vaši tipovi TypeScripta možda neće uvijek biti savršeno sinkronizirani sa stvarnim odgovorom API-ja.
Korištenje Zoda za validaciju tijekom izvođenja
Zod je popularna TypeScript biblioteka za validaciju podataka tijekom izvođenja. Omogućuje vam definiranje shema koje opisuju očekivanu strukturu vaših podataka, a zatim validiranje podataka u odnosu na te sheme tijekom izvođenja.
Instaliranje Zoda
npm install zod
Validacija API odgovora pomoću Zoda
Da biste validirali API odgovore sa Zodom, možete definirati Zod shemu koja odgovara vašem tipu TypeScripta, a zatim upotrijebiti metodu `parse` za validaciju podataka.
import { z } from 'zod';
const userSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
address: z.string().optional(),
phone: z.string().optional(),
website: z.string().optional(),
company: z.object({
name: z.string(),
catchPhrase: z.string(),
bs: z.string(),
}).optional(),
});
type User = z.infer<typeof userSchema>;
async function fetchUsers(): Promise<User[]> {
try {
const response = await axios.get<unknown>('https://jsonplaceholder.typicode.com/users');
const data = z.array(userSchema).parse(response.data);
return data;
} catch (error) {
console.error('Greška pri dohvaćanju korisnika:', error);
throw error;
}
}
U ovom primjeru, `z.array(userSchema).parse(response.data)` validira da su podaci odgovora niz objekata koji su u skladu s `userSchema`. Ako se podaci ne pridržavaju sheme, Zod će baciti grešku, kojom ćete zatim prikladno rukovati.
Napredne tehnike
Korištenje generičkih tipova za ponovno iskoristive API funkcije
Generički tipovi vam omogućuju pisanje ponovno iskoristivih API funkcija koje mogu obrađivati različite vrste podataka. Na primjer, možete stvoriti generičku funkciju `fetchData` koja može dohvaćati podatke s bilo koje API krajnje točke i vratiti ih s točnim tipom.
async function fetchData<T>(url: string): Promise<T> {
try {
const response = await axios.get<T>(url);
return response.data;
} catch (error) {
console.error(`Greška pri dohvaćanju podataka s ${url}:`, error);
throw error;
}
}
// Upotreba
fetchData<User[]>('https://jsonplaceholder.typicode.com/users').then(users => {
console.log('Korisnici:', users);
});
fetchData<{ title: string; body: string }>('https://jsonplaceholder.typicode.com/todos/1').then(todo => {
console.log('Todo', todo)
});
Korištenje presretača za globalno rukovanje pogreškama
Axios pruža presretače koji vam omogućuju presretanje zahtjeva i odgovora prije nego što ih vaš kod obradi. Možete koristiti presretače za implementaciju globalnog rukovanja pogreškama, kao što je bilježenje pogrešaka ili prikazivanje poruka o pogreškama korisniku.
axios.interceptors.response.use(
(response) => response,
(error) => {
console.error('Globalni rukovatelj pogreškama:', error);
// Prikaz poruke o pogrešci korisniku
return Promise.reject(error);
}
);
Korištenje varijabli okruženja za URL-ove API-ja
Da biste izbjegli tvrdo kodiranje URL-ova API-ja u svom kodu, možete koristiti varijable okruženja za pohranu URL-ova. To olakšava konfiguriranje vaše aplikacije za različita okruženja, kao što su razvoj, prijelaz i produkcija.
Primjer korištenja `.env` datoteke i paketa `dotenv`.
// .env
API_URL=https://api.example.com
// Instalirajte dotenv
npm install dotenv
// Uvezite i konfigurirajte dotenv
import * as dotenv from 'dotenv'
dotenv.config()
const apiUrl = process.env.API_URL || 'http://localhost:3000'; // osigurati zadanu vrijednost
async function fetchData<T>(endpoint: string): Promise<T> {
try {
const response = await axios.get<T>(`${apiUrl}/${endpoint}`);
return response.data;
} catch (error) {
console.error(`Greška pri dohvaćanju podataka s ${apiUrl}/${endpoint}:`, error);
throw error;
}
}
Zaključak
Pozivi API-ja sigurni za tip bitni su za izgradnju robusnih, održivih i web aplikacija bez grešaka. TypeScript pruža snažne značajke koje vam omogućuju definiranje tipova za API odgovore, validiranje podataka tijekom izvođenja i graciozno rukovanje pogreškama. Slijedeći najbolje prakse i tehnike navedene u ovom vodiču, možete značajno poboljšati kvalitetu i pouzdanost svojih API interakcija.
Korištenjem TypeScripta i biblioteka poput Axiosa i Zoda, možete osigurati da su vaši API pozivi sigurni za tip, da su vaši podaci validirani i da se s vašim pogreškama graciozno rukuje. To će dovesti do robusnijih i održivijih aplikacija.
Zapamtite, uvijek validirajte svoje podatke tijekom izvođenja, čak i sa sustavom tipova TypeScripta. API-ji se mogu mijenjati, a vaši tipovi možda neće uvijek biti savršeno sinkronizirani sa stvarnim odgovorom API-ja. Validacijom podataka tijekom izvođenja, možete uhvatiti potencijalne probleme prije nego što uzrokuju probleme u vašoj aplikaciji.
Sretno kodiranje!