January 19, 2026 (7mo ago) — last updated July 16, 2026 (1mo ago)

Pattern Singleton en TypeScript — Guide pratique

Guide pratique du pattern Singleton en TypeScript : usages, implémentation, pièges et alternatives (injection de dépendances). Exemples et bonnes pratiques.

← Back to blog
Cover Image for Pattern Singleton en TypeScript — Guide pratique

Dans le développement logiciel, le pattern Singleton garantit qu’une classe n’a qu’une seule instance et offre un point d’accès global. Bien utilisé, il simplifie l’accès aux ressources uniques ; mal employé, il crée de l’état global difficile à tester. Ce guide présente quand utiliser le Singleton en TypeScript, comment l’implémenter proprement et quelles alternatives privilégier pour une architecture maintenable.

Maîtriser le pattern Singleton en TypeScript : Guide complet

Un croquis au crayon d'un scribe royal portant une couronne, examinant avec soin un parchemin lumineux posé sur une table.

Dans le développement logiciel, certains outils sont puissants mais demandent de la prudence. Le pattern Singleton vise à garantir qu’une classe n’a qu’une seule instance et à fournir un point d’accès unique à cette instance1. Utilisé à bon escient, il centralise l’accès à des ressources partagées comme la configuration ou le journal de logs. Mal employé, il introduit un état global difficile à tester et à maintenir.

TypeScript étant largement adopté dans l’écosystème web et serveur, connaître les bons usages du Singleton et ses alternatives est utile pour concevoir des systèmes maintenables et testables7.

Qu’est‑ce que le pattern Singleton et quand l’utiliser ?

Imaginez un scribe royal unique qui consigne toutes les lois du royaume : cohérence et source de vérité garanties. En logiciel, une instance Singleton joue le même rôle, empêchant la création d’instances concurrentes qui pourraient produire des états contradictoires.

Quand l’utiliser :

  • Ressources réellement uniques (adaptateur matériel, gestionnaire de logs) ;
  • Objets sans état sensible ou difficile à instancier ;
  • Scénarios où la création multiple provoque un coût important ou des conflits.

Ne l’utilisez pas comme substitut d’une architecture claire : l’injection de dépendances (DI) et la composition restent préférables pour la plupart des services partagés.

Le pattern en un coup d’œil

CaractéristiqueDescription
Instance uniqueUne propriété statique stocke l’unique instance ; le constructeur est privé.
Point d’accès globalUne méthode statique (par ex. getInstance()) fournit l’accès à l’instance.
Initialisation paresseuseL’instance est créée à la première demande pour économiser les ressources.
Gestion d’étatSert de source centralisée pour une portion d’état global contrôlé.

Cas d’utilisation pratiques

  • Logger centralisé ;
  • Gestion de configuration partagée ;
  • Accès unique à une ressource matérielle.

Avantages et inconvénients

Une balance comparant des patterns de conception structurés et observables avec du code complexe, emmêlé et expérimental.

Avantages

  • Point d’accès global simple entre modules ;
  • Économie de ressources grâce à l’initialisation paresseuse ;
  • Évite la duplication d’objets coûteux.

Inconvénients

  • Couplage fort : les dépendances peuvent être cachées ;
  • État global mutable qui complique le raisonnement et les tests ;
  • Risque de conditions de course dans des environnements concurrents.

Les coûts des défauts logiciels à large échelle renforcent l’importance de bonnes pratiques architecturales : lutter contre l’état global réduit les risques et la dette technique6.

Impact sur les tests et sur l’architecture

Les Singletons rendent les tests unitaires fragiles : l’état persistant peut fuir entre tests et masquer des dépendances. Les équipes modernes préfèrent l’injection de dépendances, qui rend les dépendances explicites et faciles à remplacer par des doubles lors des tests3.

Trouver le bon équilibre : pour des bases de code héritées, préférez un refactoring incrémental vers la DI plutôt qu’un remplacement brutal.

Points clés

  • Utiliser les Singletons avec parcimonie ;
  • Favoriser la DI pour un meilleur découplage et une meilleure testabilité ;
  • Si vous employez un Singleton, assurez‑vous qu’il soit paresseux et sûr en concurrence.

Implémentation en TypeScript

Diagramme montrant ConfigManager avec un cadenas, démontrant le pattern Singleton utilisant getInstance en TypeScript.

Voici un exemple concret : un ConfigManager typé et simple. TypeScript facilite l’application des modificateurs d’accès pour imposer une instance unique2.

// Exemple de Singleton pour la gestion de configuration.
class ConfigManager {
  private static instance: ConfigManager;
  private settings: Map<string, any> = new Map();

  private constructor() {
    console.log("Initialisation de l’instance ConfigManager...");
    this.settings.set("API_URL", "https://api.example.com");
    this.settings.set("TIMEOUT", 5000);
  }

  public static getInstance(): ConfigManager {
    if (!ConfigManager.instance) {
      ConfigManager.instance = new ConfigManager();
    }
    return ConfigManager.instance;
  }

  public get(key: string): any {
    return this.settings.get(key);
  }
}

// Utilisation :
// const config = new ConfigManager(); // Erreur : constructeur privé

Exemple d’intégration dans un service

class ApiService {
  private apiUrl: string;

  constructor() {
    const config = ConfigManager.getInstance();
    this.apiUrl = config.get("API_URL");
    console.log(`ApiService initialisé avec l’URL API : ${this.apiUrl}`);
  }

  public fetchData(): void {
    console.log(`Récupération des données depuis ${this.apiUrl}...`);
  }
}

console.log("Démarrage de l’application...");
const service1 = new ApiService();
service1.fetchData();
const service2 = new ApiService();
console.log("Application terminée.");

Lorsque ce code s’exécute, ConfigManager s’initialise une seule fois, prouvant que l’instance est partagée.

Pourquoi le pattern a mauvaise réputation

Le problème principal est le couplage caché et l’état global mutable. Les Singletons peuvent masquer des dépendances qui devraient être visibles dans la signature d’un constructeur, rendant le code plus difficile à tester et à comprendre3.

Les conditions de course et les effets secondaires imprévus sont fréquents si le Singleton manipule de l’état partagé sans synchronisation. Pour des services concurrents, préférez des solutions explicites de gestion des accès.

Alternatives modernes

L’injection de dépendances (DI) est l’alternative la plus recommandée : elle rend les dépendances explicites, facilite les tests et permet de contrôler le cycle de vie des objets (transient, scoped, singleton) via un conteneur IoC45.

Exemple : passer à la DI

interface IConfigManager { get(key: string): any; }

class ApiService {
  private apiUrl: string;
  constructor(config: IConfigManager) {
    this.apiUrl = config.get("API_URL");
  }
}

Pendant les tests, vous pouvez injecter un faux IConfigManager, ce qui rend les tests rapides et isolés.

Pour des implémentations concrètes, explorez des conteneurs et frameworks comme NestJS ou InversifyJS selon vos préférences et besoins45.

Refactorer des Singletons dans une base héritée

Procédez par étapes : identifiez les usages de MySingleton.getInstance(), définissez une interface, refactorez un consommateur à la fois pour recevoir l’instance via le constructeur, puis remontez l’instance à la racine de composition ou laissez un conteneur DI la gérer.

Cette approche minimise les risques et permet d’améliorer la testabilité sans casser l’application.

FAQ — Questions & réponses rapides

Q : Les Singletons sont‑ils toujours à bannir ? A : Non. Ils conviennent pour des services véritablement uniques et sans état, mais la DI reste souvent préférable.

Q : Comment tester du code qui utilise un Singleton aujourd’hui ? A : Introduisez une interface, refactorez les consommateurs pour accepter l’interface et injectez un double de test de manière incrémentale.

Q : Quel est le meilleur moyen de supprimer les Singletons d’un projet existant ? A : Cartographiez les usages, définissez des interfaces, refactorez les consommateurs, puis injectez une instance unique depuis la racine de composition ou via un conteneur DI.

Questions & réponses de synthèse

Q1 : Quand choisir un Singleton plutôt que la DI ?

R : Choisissez le Singleton uniquement si la ressource est intrinsèquement unique, simple et sans état critique. Sinon, préférez la DI pour la testabilité et la modularité.

Q2 : Quels risques couvre la DI que le Singleton ne couvre pas ?

R : La DI expose les dépendances, facilite les mocks pour les tests et permet de gérer explicitement les cycles de vie des objets via un conteneur IoC.

Q3 : Comment limiter les effets secondaires d’un Singleton en production ?

R : Rendez l’instance paresseuse, gérez la synchronisation pour les accès concurrents, documentez son rôle et, si possible, encapsulez l’accès derrière une interface.

Prochaines étapes pour votre équipe

Lancez une discussion sur les services vraiment uniques dans votre codebase, prototypez la DI dans un module isolé et définissez des règles claires pour l’utilisation des Singletons. Les revues de code et le pairing accélèrent les refactorings en limitant les régressions.

Rappelez‑vous : aucun pattern n’est une solution miracle. Les Singletons ont leur place, mais à utiliser avec discernement et accompagnés d’interfaces propres.


1.
Martin Fowler, “Singleton,” Bliki, https://martinfowler.com/bliki/Singleton.html
2.
3.
Mark Seemann, “Singletons Are Pathological Liars,” https://blog.ploeh.dk/2010/07/28/SingletonsArePathologicalLiar/
4.
NestJS Documentation, “Dependency Injection,” https://docs.nestjs.com/fundamentals/injection
5.
InversifyJS Documentation, https://inversify.io/
6.
National Institute of Standards and Technology (NIST), Cost estimates for software defects and maintenance: “Software defects and their cost implications,” https://www.nist.gov/ (estimation historique souvent citée : coûts annuels substantiels liés aux défauts logiciels).
7.
Stack Overflow, Developer Survey 2023 — language popularity and trends, https://insights.stackoverflow.com/survey/2023
← Back to blog
🙋🏻‍♂️

L’IA écrit du code.
Vous le faites durer.

À l’ère de l’accélération de l’IA, le code propre n’est pas seulement une bonne pratique — c’est la différence entre les systèmes qui évoluent et les codebases qui s’effondrent sous leur propre poids.

Pattern Singleton en TypeScript — Guide pratique | Clean Code Guy