Trois opérandes, un point d'interrogation, deux points : la seule construction du langage qui prenne trois éléments, d'où son nom. Elle sert à choisir une valeur, pas à exécuter du code.
Définition
L'opérateur ternaire évalue une condition, puis renvoie la valeur placée avant les deux points si elle est vraie, celle placée après si elle est fausse. Sa forme est toujours la même.
const age = 20;
const statut = age >= 18 ? "majeur" : "mineur";
console.log(statut); // "majeur"
// Le même résultat avec if et else
let statutBis;
if (age >= 18) statutBis = "majeur";
else statutBis = "mineur";Les deux écritures donnent le même résultat, mais la première tient sur une ligne et permet d'utiliser const, ce que la seconde interdit puisque la variable doit être déclarée avant d'être remplie.
Une expression, pas une instruction
C'est toute la différence avec if, et la raison de son existence. Un if exécute du code ; le ternaire produit une valeur, donc il s'utilise partout où une valeur est attendue.
const n = 3;
// Dans un texte
console.log(`Il y a ${n} élément${n > 1 ? "s" : ""}`);
// Dans un retour de fonction
const etiquette = (v) => v > 0 ? "positif" : "négatif";
// Dans une transformation de tableau
console.log([1, 2].map((x) => x % 2 ? "impair" : "pair"));Aucun de ces trois emplacements n'accepte un if. C'est ce qui explique sa présence massive dans les composants d'interface, où il faut souvent choisir un libellé ou une classe au milieu du balisage.
La limite à ne pas franchir
L'opérateur s'imbrique, et c'est précisément là que le code devient illisible. Deux niveaux passent encore, au-delà la lecture devient un exercice de patience.
const n = 4, abonne = true, annuel = false;
// Acceptable
const libelle = n === 0 ? "aucun" : n === 1 ? "un" : "plusieurs";
// À éviter : trois niveaux et une condition composée
const prix = abonne ? (annuel ? 199 : 19) : (annuel ? 99 : 9);
console.log(libelle, prix); // plusieurs 19Au-delà de deux branches, un switch, un objet de correspondance ou une fonction nommée redonnent au lecteur ce que l'imbrication lui prend. Le gain de lignes ne vaut jamais la perte de clarté.
Ne le confondez pas avec la Coalescence des nuls (??). Le ternaire teste une condition et se déclenche sur toute valeur Truthy et falsy ; l'opérateur ?? ne réagit qu'à null et undefined, ce qui préserve le zéro et la chaîne vide.
Questions fréquentes
Peut-on l'utiliser sans affecter le résultat ?
Techniquement oui, mais c'est un contresens. Un ternaire dont on jette la valeur sert d'instruction conditionnelle déguisée, rôle qui revient à if. Les outils d'analyse le signalent d'ailleurs, et à juste titre : la lecture s'en trouve alourdie sans aucun gain.
Comment gérer plus de deux cas ?
Un objet de correspondance est souvent la réponse la plus lisible : les clés portent les cas, les valeurs portent les résultats, et une valeur de repli couvre les entrées inconnues. Un switch convient aussi dès qu'un traitement, et pas seulement une valeur, dépend du cas.
Faut-il des parenthèses autour de la condition ?
Elles ne sont pas obligatoires, mais elles évitent des surprises de priorité quand la condition contient une addition ou une concaténation. Une bonne habitude consiste à parenthéser le ternaire entier dès qu'il se trouve à l'intérieur d'une autre expression.