void vs never
void signifie qu’une fonction ne renvoie pas de valeur utile, tandis que never signifie qu’une fonction ne revient jamais : elle lève une erreur ou tourne indéfiniment.
Comparaison point par point
#La fonction se termine normalement
Résultat réel à l’exécution
Peut affecter une valeur de ce type à une variable
Vérification d’exhaustivité d’une union
Type de fonction de rappel (callback)
Usage typique
Exemple
#function logProgress(done: number, total: number): void {
console.log(`Progression : ${Math.round((done / total) * 100)}%`)
}
function fail(message: string): never {
throw new Error(message)
}
const result = logProgress(3, 4)
console.log(result)
try {
fail('une erreur est survenue')
} catch (error) {
console.log((error as Error).message)
}Progression : 75% undefined une erreur est survenue
Définition et utilisation
#Les deux types décrivent le plus souvent la valeur renvoyée par une fonction et s’utilisent là où une valeur ordinaire n’a pas de sens. Aucun des deux ne permet d’effectuer ensuite une opération sensée sur le résultat.
La différence est fondamentale. Une fonction de type void se termine normalement, elle ne renvoie simplement rien d’utile, et en pratique son résultat est undefined. Une fonction de type never ne revient jamais à l’endroit de l’appel : soit elle lève une exception, soit elle tourne dans une boucle infinie. never apparaît aussi comme le type de valeurs qui ne peuvent pas se produire, par ex. dans la branche default après avoir traité toutes les variantes d’une union, ce que void n’exprime jamais.
Ajoutez le type void aux fonctions qui exécutent un effet, par ex. qui journalisent, enregistrent ou modifient un état, et dont personne ne devrait utiliser le résultat. Réservez le type never aux fonctions utilitaires qui lèvent toujours une erreur, et à la vérification d’exhaustivité d’une union dans un switch. N’utilisez jamais never comme type d’une variable à laquelle vous voulez affecter quelque chose, car aucune valeur ne lui correspond.
Syntaxe
#function name(): void { … }
function fail(): never { throw new Error() }Plus d’exemples
#type Command = { kind: 'start' } | { kind: 'stop' }
function assertNever(value: never): never {
throw new Error(`Commande inconnue : ${JSON.stringify(value)}`)
}
function run(command: Command): string {
switch (command.kind) {
case 'start':
return 'Start'
case 'stop':
return 'Stop'
default:
return assertNever(command)
}
}
console.log(run({ kind: 'start' }))
console.log(run({ kind: 'stop' }))Start Stop
const log: (message: string) => void = (message) => {
console.log(message.toUpperCase())
return message.length
}
log('html')HTML
Même si la fonction transmise renvoie réellement quelque chose, le type (message: string) => void demande de l’ignorer. Grâce à cela, des fonctions comme arr.forEach(x => list.push(x)) sont correctes, bien que push() renvoie un nombre.
Bonnes pratiques
#- Ajoutez
voidexplicitement aux fonctions qui exécutent un effet de bord. Cela indique au lecteur qu’il ne devrait pas utiliser le résultat. - La fonction
assertNeverdans la branchedefaultest un moyen simple de faire rappeler par le compilateur les nouvelles variantes d’une union. - N’essayez pas de déclarer une variable de type
neverà laquelle vous voulez affecter quelque chose. Aucune valeur, mêmeundefined, ne correspond à ce type.
Entrées associées
#Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.