Introduction : pourquoi TypeScript râle-t-il sur vos propriétés ?
Vous écrivez du code en TypeScript, tout va bien... Et soudain — bam ! Une ligne ondulée rouge sous la propriété de la classe, et le compilateur affiche une phrase glaçante : Property '...' has no initializer and is not definitely assigned in the constructor. Ça vous dit quelque chose ? Si vous avez déjà travaillé avec Angular, React ou simplement avec des classes TypeScript — probablement oui.
Cette erreur est l'une des plus populaires sur Stack Overflow (des milliers de vues, des dizaines de réponses). Mais la bonne nouvelle : elle n'est pas effrayante. La mauvaise nouvelle : si vous ne comprenez pas, vous risquez de créer des bugs à l'exécution. Dans cet article, nous allons voir pourquoi cette erreur TypeScript se produit, comment la corriger et quand chaque solution est appropriée.
Que signifie l'erreur "Property has no initializer" ?
Traduisons du langage compilateur en langage humain. TypeScript vous dit : "Hé, tu as déclaré une propriété dans la classe, mais tu ne lui as pas donné de valeur initiale et tu ne l'as pas assignée dans le constructeur. Je ne suis pas sûr qu'il y aura quelque chose de pertinent quand tu accéderas à cette propriété".
Activez strict: true dans tsconfig.json — et vous activez automatiquement le flag strictPropertyInitialization. C'est lui qui est responsable de cette vérification. Le code ressemble à ceci :
class User { name: string; // ❌ Erreur ! age: number; // ❌ Erreur !}TypeScript remarque à juste titre : name et age pourraient être undefined si vous oubliez de les initialiser. Et leur type est strict string et number, sans undefined. Voilà le conflit.
Méthode n°1 : Initialisation directement dans la déclaration
Le moyen le plus simple et le plus sûr est de donner une valeur à la propriété immédiatement. C'est particulièrement pratique pour les champs avec des valeurs par défaut.
class User { name: string = 'Invité'; age: number = 0; createdAt: Date = new Date();}Quand l'utiliser : lorsque le champ a une valeur par défaut raisonnable. Par exemple, un compteur, un drapeau, une date de création. C'est une bonne pratique TypeScript — vous spécifiez explicitement l'état initial.
Méthode n°2 : Initialisation dans le constructeur
Le classique du genre. Si la valeur doit venir de l'extérieur — assignez-la dans le constructeur. TypeScript approuve cela.
class User { name: string; age: number;
constructor(name: string, age: number) { this.name = name; this.age = age; }}Important : le compilateur vérifiera que vous avez assigné une valeur à toutes les propriétés. Si vous en oubliez une — erreur à nouveau.
class User { name: string; age: number;
constructor(name: string) { this.name = name; // age non assigné — erreur ! }}C'est fait exprès : TypeScript vous protège contre un undefined accidentel. Soit vous initialisez tous les champs, soit vous autorisez explicitement qu'ils soient indéfinis.
Méthode n°3 : Opérateur definite assignment (!)
Parfois, vous savez avec certitude que la propriété sera initialisée plus tard, mais pas dans le constructeur. Par exemple, via l'injection de dépendances dans Angular ou via l'appel d'une méthode asynchrone. Utilisez alors l'assertion d'assignation définitive — un point d'exclamation après le nom de la propriété.
class UserService { user!: User; // OK, je promets qu'elle le sera
constructor() { this.initUser(); }
initUser() { this.user = new User('Alice', 30); }}Attention : c'est un outil puissant mais dangereux. Vous dites à TypeScript : "Ne vérifie pas, je sais ce que je fais". Si vous oubliez d'initialiser la propriété — vous obtiendrez undefined à l'exécution. Utilisez-le uniquement lorsque vous êtes sûr à 100%.
Méthode n°4 : Rendre la propriété optionnelle (?)
Si