Angular propose depuis la version 9 un système de typage pour les templates via le compilateur View Engine, amélioré progressivement jusqu'à Ivy. Pourtant, nombreux sont les projets qui laissent strictTemplates désactivé ou utilisent des configurations hybrides qui créent des failles de sécurité. Le typage strict des templates n'est pas une option cosmétique : c'est la différence entre une application qui compile sans erreur mais crash en production, et une application où chaque interaction est vérifiée à la compilation. Cette sécurité de type dès le template écrase les bugs liés aux accès à des propriétés inexistantes, aux changements de type de données, ou aux mutations accidentelles.
Qu'est-ce que le strict template checking ?
Le strictTemplates active plusieurs niveaux de vérification. Le plus basique, fullTemplateTypeCheck , vérifie que les expressions de binding utilisent des propriétés et méthodes qui existent réellement sur le composant. Un cran au-dessus, strictInputTypes force chaque @Input() à avoir un type explicite et contrôle que les valeurs passées sont compatibles. strictAttributeTypes valide les attributs HTML natifs selon le DOM spec. strictOutputEventTypes assure que les @Output() émettent les types corrects. strictDomLocalRefTypes type les références template ( #ref ). Enfin, strictSafeNavigationTypes empêche les accès à des propriétés optionnelles sans vérifier leur existence d'abord. Chacune de ces options peut être activée indépendamment, permettant une montée en charge progressive, mais la vraie puissance vient de les utiliser ensemble.
Mise en place : du chaos au contrôle
Pour passer en mode strict, modifiez tsconfig.json dans la section angularCompilerOptions . Commencez par strictTemplates: true , qui active automatiquement la plupart des sous-options. Vous verrez immédiatement une explosion d'erreurs de compilation. C'est attendu et sain. Ces erreurs révèlent des bugs cachés depuis des années. Plutôt que de désactiver le strict mode, résolvez-les une par une. Le chemin classique : d'abord, déclarez explicitement les types de vos @Input() et @Output() . Un composant qui reçoit @Input() user sans type déclaré ne peut pas être vérifiée. Écrivez plutôt @Input() user: User; où User est une interface bien définie. Ensuite, utilisez l'optional chaining ( ?. ) et le nullish coalescing ( ?? ) dans vos templates pour gérer les valeurs potentiellement nulles. Enfin, préférez les async pipe ou les signaux pour les données asynchrones, plutôt que des propriétés booléennes isLoading qui restent désynchronisées.
Voici un exemple concret. Avant strict mode :
@Component({...})
export class UserCardComponent {
@Input() user; // Aucun type
@Output() onDelete = new EventEmitter(); // Pas typé
deleteUser() {
this.onDelete.emit(this.user.id); // this.user.id peut ne pas exister
}
}Avec strict mode :
interface User {
id: string;
name: string;
email?: string;
}
@Component({...})
export class UserCardComponent {
@Input({ required: true }) user!: User;
@Output() onDelete = new EventEmitter<string>();
deleteUser() {
this.onDelete.emit(this.user.id); // Compilé comme safe
}
} Dans le template : {{ user?.email ?? 'Non fourni' }} compile sans avertissement.
Les pièges courants et comment les éviter
Le premier piège est de croire que strict mode ralentit la compilation. Vrai pour les très gros projets, mais la plupart des équipes voient une perte négligeable (quelques secondes). Le vrai coût est l'effort initial de refactoring. Ne le faites pas d'un coup sur un projet legacy de 500 composants. Activez progressivement : d'abord sur les nouveaux composants, puis zone par zone. Deuxième piège : trop de any ou as any pour contourner le système. Si vous écrivez (data as any).randomProperty , vous avez perdu 80% de la sécurité. Cherchez plutôt à comprendre quel type data devrait vraiment avoir. Troisième piège spécifique aux templates : oublier que les directives structurelles ( *ngIf , *ngFor ) créent des contextes de type locaux. Dans `*ngFor=