Skip to content

Bug: [prefer-optional-chain] Invalid fix when comparing against null #12204

Description

@szuend

Before You File a Bug Report Please Confirm You Have Done The Following...

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have searched for related issues and found none that matched my issue.
  • I have read the FAQ and my problem is not listed.

Playground Link

https://typescript-eslint.io/play/#ts=6.0.2&fileType=.tsx&code=FASwdgLgpgTgZgQwMZQAQDED2nUG9iqqYCu0MAtpgM4RaYAUAlAFwbYA%2BYxANt8AL7BgcYmCQQQmMKiggIAC1h0A8jAByPbk1Z1U7VF154CqGFAjEY0gLIIFAOhgIwAE0zkmqADyoADPYBWVAB%2BPBIySho6Vk8AXgA%2BA01%2BVFZDbgBuASEkKRpUOGxUWJk5RRgVdU0mLJA4VHoAQkKcdn0W%2B3DYSNpsT0bYkpbGY0IAejHUABEcKndzeXAAc3tsoA&eslintrc=N4KABGBEBOCuA2BTAzpAXGUEKQAIBcBPABxQGNoBLY-AWhXkoDt8B6Y6RAM0WloHsalfkwCG8WmQAWo5uii9o-aJHBgAviHVA&tsconfig=N4KABGBEDGD2C2AHAlgGwKYCcDyiAuysAdgM6QBcYoEEkJemy0eFYDAruuGAL4g9A&tokens=false

Repro Code

interface Foo {
  outermostFoo(): Foo|null
}

function eitherFooOrNull(): Foo | null {
  return Math.random() < 0.5 ? {outermostFoo: () => null} : null;
}

const foo = eitherFooOrNull();
if (!foo || foo.outermostFoo() !== foo) {
  // Do something.
}

ESLint Config

module.exports = {
  parser: "@typescript-eslint/parser",
  rules: {
    "@typescript-eslint/prefer-optional-chain": "error",
  },
};

tsconfig

{
  "compilerOptions": {
    "strict": true
  }
}

Expected Result

No error/fix happening.

Actual Result

The if is re-written

const foo = eitherFooOrNull();
if (foo?.outermostFoo() !== foo) {
  // Do something.
}

This is a true semantic change, because optional chaining coerces the null into an undefined, which means in the case where foo is null, the if changes to undefined !== null. We will no longer take the if branch.

Additional Info

Broken in the upgrade from 8.47.0 to 8.52.0. Upgrading typescript-eslint in the Chrome DevTools code base causes actual test failures due to this rewrite and we had to disable the rule.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingduplicateThis issue or pull request already existspackage: eslint-pluginIssues related to @typescript-eslint/eslint-plugin

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions