Help me bij het implementeren van type-veilige API-aanvraag- en antwoordverwerking in TypeScript voor {{api_type}}.
description
Door type-veilige API-aanvraag- en antwoordverwerking te implementeren, kan ik runtime-fouten verminderen, de onderhoudbaarheid van de code verbeteren en zorgen dat mijn gegevensstructuren consistent blijven in de hele applicatie.
prompt
try_prompt
Ik heb begeleiding nodig over hoe ik API-aanvragen en antwoorden effectief kan beheren op een type-veilige manier met behulp van TypeScript voor {{api_type}}. Geef voorbeelden v ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht en voorbeelden om API-aanvragen en -antwoorden type-veilig te beheren met TypeScript voor REST APIs.
### 1. Definieer request- en response-typen
Begin met het definiëren van duidelijke TypeScript-interfaces voor je API-aanvragen en -antwoorden:
```typescript
// Voorbeeld: Gebruiker aanmaken
interface CreateUserRequest {
naam: string;
email: string;
leeftijd?: number; // optioneel
}
interface UserResponse {
id: string;
naam: string;
email: string;
createdAt: string;
}
```
### 2. Functie om API-aanvragen te doen met type-veiligheid
Gebruik generieke functies die de request- en response-typen kennen:
```typescript
async function apiRequest<T, R>(
url: string,
options: RequestInit,
): Promise<R> {
const response = await fetch(url, options);
if (!response.ok) {
// Foutafhandeling
const errorText = await response.text();
throw new Error(`Fout bij API-aanroep: ${response.status} - ${errorText}`);
}
const data: R = await response.json();
return data;
}
```
### 3. Aanroepen met type-veiligheid
Voor een POST-aanvraag om een gebruiker aan te maken:
```typescript
const nieuwUser: CreateUserRequest = {
naam: 'Jan Jansen',
email: 'jan@example.com',
};
apiRequest<CreateUserRequest, UserResponse>('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(nieuwUser),
})
.then((user) => {
console.log('Gebruiker aangemaakt:', user);
})
.catch((error) => {
console.error('Fout:', error);
});
```
### 4. Foutafhandeling en type-veiligheid
- Controleer of de response succesvol is (`response.ok`).
- Gooi expliciet fouten met relevante informatie.
- Gebruik `try-catch` blokken bij async/await.
Voorbeeld met `try-catch`:
```typescript
async function createUser(user: CreateUserRequest): Promise<UserResponse> {
try {
const result = await apiRequest<CreateUserRequest, UserResponse>('https://api.example.com/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user),
});
return result;
} catch (err) {
// Afhandeling of her-throw
console.error('Error bij aanmaken gebruiker:', err);
throw err;
}
}
```
### 5. Samenvatting
- Definieer duidelijk je request- en response-typen.
- Gebruik generieke functies voor API-aanroepen.
- Behandel fouten expliciet en overzichtelijk.
- Zorg dat je TypeScript-typen je hele proces begeleiden, van request tot response.
Wil je nog een uitgebreider voorbeeld of specifieke hulp bij andere API-methoden?
provider: deepseek
model: deepseek-chat
Hier is een uitgebreide handleiding voor type-veilige API-interacties met TypeScript voor REST:
## 1. Basis Type Definities
```typescript
// Basis API response types
interface ApiResponse<T> {
data: T;
status: number;
message?: string;
}
interface ApiError {
code: string;
message: string;
details?: unknown;
}
// Voorbeeld domein types
interface User {
id: string;
name: string;
email: string;
createdAt: Date;
}
interface CreateUserRequest {
name: string;
email: string;
password: string;
}
```
## 2. Generic API Client Implementatie
```typescript
class ApiClient {
private baseURL: string;
constructor(baseURL: string) {
this.baseURL = baseURL;
}
async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
headers: {
'Content-Type': 'application/json',
...options.headers,
},
...options,
});
if (!response.ok) {
const errorData: ApiError = await response.json().catch(() => ({
code: 'PARSE_ERROR',
message: 'Failed to parse error response',
}));
throw new ApiError(errorData.message, response.status, errorData.code);
}
const data: T = await response.json();
return {
data,
status: response.status,
};
} catch (error) {
if (error instanceof ApiError) {
throw error;
}
throw new ApiError(
'Network error occurred',
0,
'NETWORK_ERROR'
);
}
}
// Type-veilige methoden
async get<T>(endpoint: string): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, { method: 'GET' });
}
async post<T, U>(endpoint: string, body: U): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, {
method: 'POST',
body: JSON.stringify(body),
});
}
async put<T, U>(endpoint: string, body: U): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, {
method: 'PUT',
body: JSON.stringify(body),
});
}
async delete<T>(endpoint: string): Promise<ApiResponse<T>> {
return this.request<T>(endpoint, { method: 'DELETE' });
}
}
```
## 3. Custom Error Klasse
```typescript
class ApiError extends Error {
constructor(
message: string,
public statusCode: number,
public code: string
) {
super(message);
this.name = 'ApiError';
}
}
```
## 4. Type-veilige Service Laag
```typescript
class UserService {
private apiClient: ApiClient;
constructor() {
this.apiClient = new ApiClient('https://api.jouw-domein.nl');
}
// Type-veilige methoden met gedefinieerde request/response types
async getUser(id: string): Promise<User> {
const response = await this.apiClient.get<User>(`/users/${id}`);
return response.data;
}
async createUser(userData: CreateUserRequest): Promise<User> {
const response = await this.apiClient.post<User, CreateUserRequest>(
'/users',
userData
);
return response.data;
}
async updateUser(id: string, userData: Partial<User>): Promise<User> {
const response = await this.apiClient.put<User, Partial<User>>(
`/users/${id}`,
userData
);
return response.data;
}
async deleteUser(id: string): Promise<void> {
await this.apiClient.delete(`/users/${id}`);
}
}
```
## 5. Runtime Validatie met Zod
```typescript
import { z } from 'zod';
// Schema validatie
const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1),
email: z.string().email(),
createdAt: z.string().datetime(),
});
const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
password: z.string().min(8),
});
// Type inference van Zod schema's
type ValidatedUser = z.infer<typeof UserSchema>;
type ValidatedCreateUser = z.infer<typeof CreateUserSchema>;
// Validatie wrapper
class ValidatedApiClient extends ApiClient {
async validatedRequest<T>(
endpoint: string,
schema: z.ZodSchema<T>,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const response = await this.request<unknown>(endpoint, options);
try {
const validatedData = schema.parse(response.data);
return {
...response,
data: validatedData,
};
} catch (error) {
if (error instanceof z.ZodError) {
throw new ApiError(
'Response validation failed',
422,
'VALIDATION_ERROR'
);
}
throw error;
}
}
}
```
## 6. Gebruik in Componenten
```typescript
// React component voorbeeld
const UserComponent: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const userService = new UserService();
const fetchUser = async (userId: string) => {
setLoading(true);
setError(null);
try {
const userData = await userService.getUser(userId);
setUser(userData);
} catch (err) {
if (err instanceof ApiError) {
setError(`Fout: ${err.message} (Code: ${err.code})`);
} else {
setError('Onverwachte fout opgetreden');
}
} finally {
setLoading(false);
}
};
const createNewUser = async (userData: CreateUserRequest) => {
try {
const newUser = await userService.createUser(userData);
console.log('Gebruiker aangemaakt:', newUser);
} catch (err) {
// Type-veilige error handling
if (err instanceof ApiError) {
switch (err.code) {
case 'VALIDATION_ERROR':
console.error('Validatiefout:', err.message);
break;
case 'NETWORK_ERROR':
console.error('Netwerkfout:', err.message);
break;
default:
console.error('API fout:', err.message);
}
}
}
};
if (loading) return <div>Laden...</div>;
if (error) return <div>{error}</div>;
return (
<div>
{user && (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
)}
</div>
);
};
```
## 7. Geavanceerde Features
```typescript
// Request/response interceptors
class ExtendedApiClient extends ApiClient {
private requestInterceptors: Array<(config: RequestInit) => RequestInit> = [];
private responseInterceptors: Array<(response: Response) => Response> = [];
addRequestInterceptor(interceptor: (config: RequestInit) => RequestInit) {
this.requestInterceptors.push(interceptor);
}
addResponseInterceptor(interceptor: (response: Response) => Response) {
this.responseInterceptors.push(interceptor);
}
async request<T>(endpoint: string, options: RequestInit = {}): Promise<ApiResponse<T>> {
// Request interceptors toepassen
let processedOptions = options;
for (const interceptor of this.requestInterceptors) {
processedOptions = interceptor(processedOptions);
}
const response = await super.request<T>(endpoint, processedOptions);
return response;
}
}
// Automatische retry logica
class RetryApiClient extends ApiClient {
async requestWithRetry<T>(
endpoint: string,
options: RequestInit = {},
maxRetries: number = 3
): Promise<ApiResponse<T>> {
let lastError: Error;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await this.request<T>(endpoint, options);
} catch (error) {
lastError = error as Error;
if (error instanceof ApiError && error.statusCode >= 500) {
// Alleen retry bij server errors
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, attempt) * 1000)
);
continue;
}
break;
}
}
throw lastError!;
}
}
```
## Belangrijkste Voordelen:
1. **Compile-time type safety**: TypeScript vangt type fouten tijdens ontwikkeling
2. **Runtime validatie**: Zod zorgt voor data-integriteit
3. **Uitbreidbare architectuur**: Makkelijk aan te passen voor nieuwe endpoints
4. **Consistente error handling**: Gestandaardiseerde foutafhandeling
5. **Herbruikbare componenten**: Generic types voor maximale herbruikbaarheid
Deze aanpak zorgt voor robuuste, onderhoudbare en type-veilige API-interacties in je TypeScript applicatie.

