Mestre type-sikre API-kall i TypeScript for robuste, vedlikeholdbare og feilfrie webapplikasjoner. Lær beste praksiser og avanserte teknikker.
Type-sikre API-kall med TypeScript: En omfattende guide
I moderne webutvikling er interaksjon med APIer en grunnleggende oppgave. TypeScript, med sitt kraftige typesystem, gir en betydelig fordel når det gjelder å sikre påliteligheten og vedlikeholdbarheten til applikasjonene dine ved å muliggjøre type-sikre API-kall. Denne guiden vil utforske hvordan du kan utnytte TypeScript sine funksjoner for å bygge robuste og feilfrie API-interaksjoner, og dekke beste praksiser, avanserte teknikker og eksempler fra den virkelige verden.
Hvorfor typesikkerhet er viktig for API-kall
Når du arbeider med APIer, har du i hovedsak å gjøre med data som kommer fra en ekstern kilde. Disse dataene er kanskje ikke alltid i det formatet du forventer, noe som kan føre til kjøretidsfeil og uventet oppførsel. Typesikkerhet gir et viktig lag med beskyttelse ved å verifisere at dataene du mottar samsvarer med en forhåndsdefinert struktur, og fanger opp potensielle problemer tidlig i utviklingsprosessen.
- Reduserte kjøretidsfeil: Typekontroll ved kompileringstid hjelper deg med å identifisere og fikse typerelaterte feil før de når produksjon.
- Forbedret kodevedlikehold: Tydelige typedefinisjoner gjør koden din lettere å forstå og endre, noe som reduserer risikoen for å introdusere feil under refaktorering.
- Forbedret lesbarhet av kode: Typeannotasjoner gir verdifull dokumentasjon, noe som gjør det lettere for utviklere å forstå de forventede datastrukturene.
- Bedre utvikleropplevelse: IDE-støtte for typekontroll og autofullføring forbedrer utvikleropplevelsen betydelig og reduserer sannsynligheten for feil.
Sette opp TypeScript-prosjektet ditt
Før du dykker ned i API-kall, må du sørge for at du har et TypeScript-prosjekt satt opp. Hvis du starter fra bunnen av, kan du initialisere et nytt prosjekt ved å bruke:
npm init -y
npm install typescript --save-dev
tsc --init
Dette vil opprette en `tsconfig.json`-fil med standard TypeScript-kompilatoralternativer. Du kan tilpasse disse alternativene for å passe prosjektets behov. Du kan for eksempel aktivere streng modus for strengere typekontroll:
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Definere typer for API-responser
Det første trinnet i å oppnå type-sikre API-kall er å definere TypeScript-typer som representerer strukturen til dataene du forventer å motta fra APIet. Dette gjøres vanligvis ved hjelp av `interface`- eller `type`-deklarasjoner.
Bruke grensesnitt
Grensesnitt er en kraftig måte å definere formen på et objekt. Hvis du for eksempel henter en liste over brukere fra et API, kan du definere et grensesnitt som dette:
interface User {
id: number;
name: string;
email: string;
address?: string; // Valgfri egenskap
phone?: string; // Valgfri egenskap
website?: string; // Valgfri egenskap
company?: {
name: string;
catchPhrase: string;
bs: string;
};
}
`?` etter et egenskapsnavn indikerer at egenskapen er valgfri. Dette er nyttig for å håndtere API-responser der visse felt kan mangle.
Bruke typer
Typer ligner på grensesnitt, men tilbyr mer fleksibilitet, inkludert muligheten til å definere unionstyper og krysstyper. Du kan oppnå det samme resultatet som grensesnittet ovenfor ved å bruke en type:
type User = {
id: number;
name: string;
email: string;
address?: string; // Valgfri egenskap
phone?: string; // Valgfri egenskap
website?: string; // Valgfri egenskap
company?: {
name: string;
catchPhrase: string;
bs: string;
};
};
For enkle objektstrukturer er grensesnitt og typer ofte utskiftbare. Typer blir imidlertid kraftigere når du har å gjøre med mer komplekse scenarier.
Gjøre API-kall med Axios
Axios er en populær HTTP-klient for å gjøre API-forespørsler i JavaScript og TypeScript. Det gir et rent og intuitivt API, noe som gjør det enkelt å håndtere forskjellige HTTP-metoder, forespørselshoder og responsdata.
Installere Axios
npm install axios
Gjøre et typet API-kall
For å gjøre et type-sikkert API-kall med Axios, kan du bruke `axios.get`-metoden og spesifisere forventet responstype ved hjelp av generiske typer:
import axios from 'axios';
async function fetchUsers(): Promise {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
return response.data;
} catch (error) {
console.error('Feil ved henting av brukere:', error);
throw error;
}
}
fetchUsers().then(users => {
users.forEach(user => {
console.log(user.name);
});
});
I dette eksemplet forteller `axios.get
Håndtere forskjellige HTTP-metoder
Axios støtter forskjellige HTTP-metoder, inkludert `GET`, `POST`, `PUT`, `DELETE` og `PATCH`. Du kan bruke de tilsvarende metodene for å gjøre forskjellige typer API-forespørsler. For eksempel, for å opprette en ny bruker, kan du bruke `axios.post`-metoden:
async function createUser(user: Omit): Promise {
try {
const response = await axios.post('https://jsonplaceholder.typicode.com/users', user);
return response.data;
} catch (error) {
console.error('Feil ved oppretting av bruker:', 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('Opprettet bruker:', user);
});
I dette eksemplet oppretter `Omit
Bruke Fetch API
Fetch API er et innebygd JavaScript API for å gjøre HTTP-forespørsler. Selv om det er mer grunnleggende enn Axios, kan det også brukes med TypeScript for å oppnå type-sikre API-kall. Du foretrekker det kanskje for å unngå å legge til en avhengighet hvis det passer dine behov.
Gjøre et typet API-kall med Fetch
For å gjøre et type-sikkert API-kall med Fetch, kan du bruke `fetch`-funksjonen og deretter parse responsen som JSON, og spesifisere den forventede responstypen:
async function fetchUsers(): Promise {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data: User[] = await response.json();
return data;
} catch (error) {
console.error('Feil ved henting av brukere:', error);
throw error;
}
}
fetchUsers().then(users => {
users.forEach(user => {
console.log(user.name);
});
});
I dette eksemplet forteller `const data: User[] = await response.json();` TypeScript at responsdataene skal behandles som en array av `User`-objekter. Dette lar TypeScript utføre typekontroll og autofullføring.
Håndtere forskjellige HTTP-metoder med Fetch
For å gjøre forskjellige typer API-forespørsler med Fetch, kan du bruke `fetch`-funksjonen med forskjellige alternativer, for eksempel `method`- og `body`-alternativene. For eksempel, for å opprette en ny bruker, kan du bruke følgende kode:
async function createUser(user: Omit): Promise {
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 error! status: ${response.status}`);
}
const data: User = await response.json();
return data;
} catch (error) {
console.error('Feil ved oppretting av bruker:', 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('Opprettet bruker:', user);
});
Håndtere API-feil
Feilhåndtering er et kritisk aspekt ved API-kall. APIer kan mislykkes av mange årsaker, inkludert problemer med nettverkstilkobling, serverfeil og ugyldige forespørsler. Det er viktig å håndtere disse feilene på en elegant måte for å forhindre at applikasjonen din krasjer eller viser uventet oppførsel.
Bruke Try-Catch-blokker
Den vanligste måten å håndtere feil i asynkron kode er å bruke try-catch-blokker. Dette lar deg fange opp eventuelle unntak som kastes under API-kallet og håndtere dem på riktig måte.
async function fetchUsers(): Promise {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
return response.data;
} catch (error) {
console.error('Feil ved henting av brukere:', error);
// Håndter feilen, f.eks. vis en feilmelding til brukeren
throw error; // Kast feilen på nytt for å tillate at kallende kode også kan håndtere den
}
}
Håndtere spesifikke feilkoder
APIer returnerer ofte spesifikke feilkoder for å indikere hvilken type feil som oppstod. Du kan bruke disse feilkodene til å gi mer spesifikk feilhåndtering. For eksempel kan det hende du vil vise en annen feilmelding for en 404 Not Found-feil enn for en 500 Internal Server Error.
async function fetchUser(id: number): Promise {
try {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`);
return response.data;
} catch (error: any) {
if (error.response?.status === 404) {
console.log(`Bruker med ID ${id} ble ikke funnet.`);
return null; // Eller kast en tilpasset feil
} else {
console.error('Feil ved henting av bruker:', error);
throw error;
}
}
}
fetchUser(123).then(user => {
if (user) {
console.log('Bruker:', user);
} else {
console.log('Bruker ble ikke funnet.');
}
});
Opprette tilpassede feiltyper
For mer komplekse feilhåndteringsscenarier kan du opprette tilpassede feiltyper for å representere forskjellige typer API-feil. Dette lar deg gi mer strukturert feilinformasjon og håndtere feil mer effektivt.
class ApiError extends Error {
constructor(public statusCode: number, message: string) {
super(message);
this.name = 'ApiError';
}
}
async function fetchUser(id: number): Promise {
try {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`);
return response.data;
} catch (error: any) {
if (error.response?.status === 404) {
throw new ApiError(404, `Bruker med ID ${id} ble ikke funnet.`);
} else {
console.error('Feil ved henting av bruker:', error);
throw new ApiError(500, 'Intern serverfeil'); // Eller en annen passende statuskode
}
}
}
fetchUser(123).catch(error => {
if (error instanceof ApiError) {
console.error(`API-feil: ${error.statusCode} - ${error.message}`);
} else {
console.error('En uventet feil oppstod:', error);
}
});
Datavalidering
Selv med TypeScript sitt typesystem er det avgjørende å validere dataene du mottar fra APIer ved kjøretid. APIer kan endre responsstrukturen sin uten varsel, og TypeScript-typene dine er kanskje ikke alltid perfekt synkronisert med APIets faktiske respons.
Bruke Zod for kjøretidsvalidering
Zod er et populært TypeScript-bibliotek for kjøretidsdatavalidering. Det lar deg definere skjemaer som beskriver den forventede strukturen til dataene dine, og deretter validere dataene mot disse skjemaene ved kjøretid.
Installere Zod
npm install zod
Validere API-responser med Zod
For å validere API-responser med Zod, kan du definere et Zod-skjema som tilsvarer TypeScript-typen din, og deretter bruke `parse`-metoden for å validere dataene.
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;
async function fetchUsers(): Promise {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
const data = z.array(userSchema).parse(response.data);
return data;
} catch (error) {
console.error('Feil ved henting av brukere:', error);
throw error;
}
}
I dette eksemplet validerer `z.array(userSchema).parse(response.data)` at responsdataene er en array av objekter som samsvarer med `userSchema`. Hvis dataene ikke samsvarer med skjemaet, vil Zod kaste en feil, som du deretter kan håndtere på riktig måte.
Avanserte teknikker
Bruke generiske typer for gjenbrukbare API-funksjoner
Generiske typer lar deg skrive gjenbrukbare API-funksjoner som kan håndtere forskjellige typer data. For eksempel kan du opprette en generisk `fetchData`-funksjon som kan hente data fra et hvilket som helst API-endepunkt og returnere dem med riktig type.
async function fetchData(url: string): Promise {
try {
const response = await axios.get(url);
return response.data;
} catch (error) {
console.error(`Feil ved henting av data fra ${url}:`, error);
throw error;
}
}
// Bruk
fetchData('https://jsonplaceholder.typicode.com/users').then(users => {
console.log('Brukere:', users);
});
fetchData<{ title: string; body: string }>('https://jsonplaceholder.typicode.com/todos/1').then(todo => {
console.log('Todo', todo)
});
Bruke interceptors for global feilhåndtering
Axios tilbyr interceptors som lar deg fange opp forespørsler og responser før de håndteres av koden din. Du kan bruke interceptors til å implementere global feilhåndtering, for eksempel å logge feil eller vise feilmeldinger til brukeren.
axios.interceptors.response.use(
(response) => response,
(error) => {
console.error('Global feilhåndterer:', error);
// Vis en feilmelding til brukeren
return Promise.reject(error);
}
);
Bruke miljøvariabler for API-URLer
For å unngå å hardkode API-URLer i koden din, kan du bruke miljøvariabler til å lagre URLene. Dette gjør det enklere å konfigurere applikasjonen din for forskjellige miljøer, for eksempel utvikling, testing og produksjon.
Eksempel ved bruk av `.env`-fil og `dotenv`-pakke.
// .env
API_URL=https://api.example.com
// Installer dotenv
npm install dotenv
// Importer og konfigurer dotenv
import * as dotenv from 'dotenv'
dotenv.config()
const apiUrl = process.env.API_URL || 'http://localhost:3000'; // provide a default value
async function fetchData(endpoint: string): Promise {
try {
const response = await axios.get(`${apiUrl}/${endpoint}`);
return response.data;
} catch (error) {
console.error(`Feil ved henting av data fra ${apiUrl}/${endpoint}:`, error);
throw error;
}
}
Konklusjon
Type-sikre API-kall er avgjørende for å bygge robuste, vedlikeholdbare og feilfrie webapplikasjoner. TypeScript gir kraftige funksjoner som lar deg definere typer for API-responser, validere data ved kjøretid og håndtere feil på en elegant måte. Ved å følge beste praksiser og teknikker som er skissert i denne guiden, kan du forbedre kvaliteten og påliteligheten til API-interaksjonene dine betydelig.
Ved å bruke TypeScript og biblioteker som Axios og Zod, kan du sikre at API-kallene dine er type-sikre, dataene dine er validert og feilene dine håndteres på en elegant måte. Dette vil føre til mer robuste og vedlikeholdbare applikasjoner.
Husk å alltid validere dataene dine ved kjøretid, selv med TypeScript sitt typesystem. APIer kan endres, og typene dine er kanskje ikke alltid perfekt synkronisert med APIets faktiske respons. Ved å validere dataene dine ved kjøretid kan du fange opp potensielle problemer før de forårsaker problemer i applikasjonen din.
God koding!