Client HTTP en TypeScript : faire des requêtes correctement de A à Z

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Client HTTP en TypeScript : faire des requêtes correctement de A à Z

\n\n

Le développement web moderne est impensable sans interaction avec des serveurs distants. Que ce soit pour récupérer des données d'une API REST, envoyer des formulaires ou télécharger des fichiers — les requêtes HTTP sont le fondement de l'architecture client-serveur. TypeScript, avec son typage strict et ses outils puissants, permet de rendre le travail avec les requêtes HTTP non seulement sûr, mais aussi facile à maintenir. Dans cet article, nous allons voir comment créer un client HTTP bien conçu en TypeScript, éviter les erreurs courantes et écrire un code qui fonctionne de manière prévisible.

\n\n

1. Les bases : fetch API et son typage

\n\n

Intégré au navigateur, fetch est un outil moderne et flexible pour effectuer des requêtes HTTP. Cependant, son utilisation en TypeScript nécessite un typage correct de la réponse. Par défaut, fetch retourne Promise<Response>, et nous devons spécifier explicitement les données que nous attendons.

\n\n
interface User {\n  id: number;\n  name: string;\n  email: string;\n}\n\nasync function getUser(id: number): Promise<User> {\n  const response = await fetch(`https://api.example.com/users/${id}`);\n  \n  if (!response.ok) {\n    throw new Error(`HTTP error! status: ${response.status}`);\n  }\n  \n  const data: User = await response.json();\n  return data;\n}\n
\n\n

Notez la vérification de response.ok. C'est crucial : même si le serveur renvoie une erreur (404, 500, etc.), fetch ne lèvera pas d'exception automatiquement. Nous devons gérer le statut manuellement.

\n\n

Pour les requêtes POST avec un corps, il est nécessaire de spécifier l'en-tête Content-Type :

\n\n
async function createUser(userData: Omit<User, 'id'>): Promise<User> {\n  const response = await fetch('https://api.example.com/users', {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n    },\n    body: JSON.stringify(userData),\n  });\n\n  if (!response.ok) {\n    throw new Error(`Failed to create user: ${response.statusText}`);\n  }\n\n  return response.json();\n}\n
\n\n

2. Création d'un client HTTP universel

\n\n

Au lieu d'écrire fetch à chaque fois depuis zéro, il est préférable de créer une enveloppe — un client HTTP universel. Cela permet de gérer de manière centralisée l'URL de base, les en-têtes et la gestion des erreurs. Voici un exemple basé sur les classes :

\n\n
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n\ninterface RequestConfig<TBody = unknown> {\n  method: HttpMethod;\n  url: string;\n  body?: TBody;\n  headers?: Record<string, string>;\n  params?: Record<string, string>;\n}\n\nclass HttpClient {\n  private baseUrl: string;\n  private defaultHeaders: Record<string, string>;\n\n  constructor(baseUrl: string, defaultHeaders: Record<string, string> = {}) {\n    this.baseUrl = baseUrl;\n    this.defaultHeaders = {\n      'Content-Type': 'application/json',\n      ...defaultHeaders,\n    };\n  }\n\n  private async request<TResponse, TBody = unknown>(\n    config: RequestConfig<TBody>\n  ): Promise<TResponse> {\n    const url = new URL(`${this.baseUrl}${config.url}`);\n    \n    if (config.params) {\n      Object.entries(config.params).forEach(([key, value]) => {\n        url.searchParams.append(key, value);\n      });\n    }\n\n    const response = await fetch(url.toString(), {\n      method: config.method,\n      headers: { ...this.defaultHeaders, ...config.headers },\n      body: config.body ? JSON.stringify(config.body) : undefined,\n    });\n\n    if (!response.ok) {\n      const errorBody = await response.text();\n      throw new Error(`Request failed: ${response.status} ${response.statusText}. Body: ${errorBody}`);\n    }\n\n    // Pour DELETE ou d'autres méthodes qui peuvent ne pas retourner de corps\n    if (response.status === 204) {\n      return undefined as TResponse;\n    }\n\n    return response.jso                

Blogs

Book Recommendations