Type Assertions

Intro aux assertions de type

Nous savons que TypeScript peut deviner le type d'une donnée de manière implicite et s'il ne la trouve pas il affecte le type any.

Parfois il arrive qu'il sache le type à attribuer mais manque de précision.

Pour aider TypeScript à être plus précis sur le type, vous pouvez utiliser ce qu'on appelle l'assertion de type (type assertion en anglais).

Cas concret

Par exemple, si vous utilisez document.getElementById('myInput')

Vous savez que c'est un input (HTMLInputElement), mais TypeScript ne le sait pas alors il va attribuer un type moins précis : HTMLElement ou null.

Si vous essayez d'appeler une méthode propre à un input vous déclencherez une erreur :

const myInput = document.getElementById('myInput');
myInput.checkValidity();
src/demo.ts:10:9 - error TS2339: Property 'checkValidity' does not exist on type 'HTMLElement'.
                                                                                               
10 myInput.checkValidity();

Utilisons l'assertion de types pour remédier à ce problème !

Deux syntaxes sont possibles.

1re variante :

const myInput = document.getElementById('myInput') as HTMLInputElement;
myInput.checkValidity();

2e variante :

Cette variante ne fonctionnera pas dans les fichiers .tsx (utilisés par React), vous devrez utiliser la première version avec le mot-clé as.

const myInput = <HTMLInputElement>document.getElementById('myInput');
myInput.checkValidity();

Vous avez sûrement remarqué que TypeScript ne signale pas d'erreurs depuis que nous avons utilisé l'assertion de type :

Il faut bien faire attention lorsque vous utilisez cette fonctionnalité car cela réduit le champ d'action de TypeScript et donc il verra moins d'erreurs potentielles !

Vous devez être certain que l'élément HTML (id=myInput) sera présent dans le DOM sinon vous pourrez rencontrer une erreur de runtime comme celle-là :

Uncaught TypeError: Cannot read properties of null (reading 'checkValidity')
    at <anonymous>:1:33
(anonymous) @ VM517:1

Vous pouvez rajouter une condition pour renforcer la fiabilité de votre code :

const myInput = <HTMLInputElement>document.getElementById('myInput');
if(myInput) {
    myInput.checkValidity();
}

L'assertion de type est donc à utiliser à bon escient.

Pour la liste des éléments HTML, vous pouvez consulter la doc de Mozilla :

Référence Web API. MDN. Mozilla

Cas impossibles

TypeScript autorise uniquement l'assertion de type sur des types plus spécifiques ou moins spécifiques.

Dans notre exemple précédent, nous avons pu passer du type HTMLElement au type HTMLInputElement car c'est un type plus précis que HTMLElement mais toujours de la même famille.

Voici un exemple qui ne fonctionnera pas :

const firstName = "Flo" as number;
src/demo.ts:11:19 - error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unkn
own' first.

11 const firstName = "Flo" as number;