oxc-project/oxc · warning · OxcDiagnostic

Prefer ternary expressions over simple `if-else` statements.

Error message

Prefer ternary expressions over simple `if-else` statements.

What it means

This is the oxlint rule `unicorn/prefer-ternary`. It fires on a simple `if`/`else` whose two branches each contain exactly one statement that assigns to the same target with `=` (via `is_same_expression`/`is_same_member_expression` checks), suggesting a conditional (ternary) expression instead. The `always` (default) option enforces it whenever merging is safe; `only-single-line` restricts it to single-line condition and branches.

Source

Thrown at crates/oxc_linter/src/rules/unicorn/prefer_ternary.rs:22

use serde::Deserialize;

use oxc_ast::{
    AstKind,
    ast::{AssignmentTarget, Expression, IfStatement, MemberExpression, Statement},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::{GetSpan, Span};

use crate::{
    AstNode,
    context::LintContext,
    rule::{DefaultRuleConfig, Rule},
    utils::{is_same_expression, is_same_member_expression, static_string_value},
};

fn prefer_ternary_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Prefer ternary expressions over simple `if-else` statements.")
        .with_help("Rewrite this `if`/`else` as a ternary expression.")
        .with_label(span)
}

#[derive(Debug, Clone, Copy, Default, Deserialize, JsonSchema, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum PreferTernaryOption {
    /// Always enforce ternary usage when the branches can be safely merged.
    #[default]
    Always,
    /// Only enforce ternary usage when the condition and both branches are single-line.
    OnlySingleLine,
}

#[derive(Debug, Default, Clone, Deserialize)]
pub struct PreferTernary(PreferTernaryOption);

declare_oxc_lint!(

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Merge into a ternary: `a = cond ? 1 : 2;` (watch operator precedence — parenthesize the ternary inside larger expressions).
  2. If the branches or condition are long, extract them: `a = cond ? longExprA() : longExprB();` or keep the if/else and set the rule to `only-single-line` in `.oxlintrc.json`.
  3. If your style guide bans ternaries in statements, disable `unicorn/prefer-ternary` outright.

Example fix

// before
let level;
if (isDev) {
  level = 'debug';
} else {
  level = 'info';
}

// after
const level = isDev ? 'debug' : 'info';
Defensive patterns

Strategy: validation

Validate before calling

// Express dual assignment as a conditional from the start
const level = isDev ? 'debug' : 'info';
// CI: npx oxlint --deny-warn unicorn/prefer-ternary src/

Prevention

When it happens

Trigger: `if (cond) { a = 1; } else { a = 2; }`, or branches assigning the same member (`obj.x = ...` in both arms), where both branch bodies are single assignment expression statements to a syntactically identical target. Non-assignment branches, differing targets, or `else if` chains with mixed shapes are not flagged.

Common situations: Config/flag selection code (`if (dev) { level = 'debug'; } else { level = 'info'; }`); teams that find nested ternaries unreadable often set `only-single-line` or disable the rule, since the merged form can hurt readability when condition or values grow.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/690797763d7cd0c2. Report an issue: GitHub.