diff --git a/packages/eslint-plugin/docs/rules/prefer-optional-chain.md b/packages/eslint-plugin/docs/rules/prefer-optional-chain.md
index 1f42754e0f75..4d0e0871c73b 100644
--- a/packages/eslint-plugin/docs/rules/prefer-optional-chain.md
+++ b/packages/eslint-plugin/docs/rules/prefer-optional-chain.md
@@ -22,6 +22,10 @@ function myFunc(foo: T | null) {
 function myFunc(foo: T | null) {
   return foo && foo.a && foo.a.b && foo.a.b.c;
 }
+// or
+function myFunc(foo: T | null) {
+  return (((foo || {}).a || {}).b || {}).c;
+}
 
 function myFunc(foo: T | null) {
   return foo?.['a']?.b?.c;
@@ -57,6 +61,9 @@ foo && foo.a && foo.a.b && foo.a.b.c;
 foo && foo['a'] && foo['a'].b && foo['a'].b.c;
 foo && foo.a && foo.a.b && foo.a.b.method && foo.a.b.method();
 
+(((foo || {}).a || {}).b {}).c;
+(((foo || {})['a'] || {}).b {}).c;
+
 // this rule also supports converting chained strict nullish checks:
 foo &&
   foo.a != null &&
diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts
index 109deaa6d60d..b3815e09ef97 100644
--- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts
+++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts
@@ -1,5 +1,7 @@
-import { AST_NODE_TYPES, TSESTree, TSESLint } from '@typescript-eslint/utils';
+import * as ts from 'typescript';
 import * as util from '../util';
+import { AST_NODE_TYPES, TSESTree, TSESLint } from '@typescript-eslint/utils';
+import { isBinaryExpression } from 'tsutils';
 
 type ValidChainTarget =
   | TSESTree.BinaryExpression
@@ -47,7 +49,68 @@ export default util.createRule({
   defaultOptions: [],
   create(context) {
     const sourceCode = context.getSourceCode();
+    const parserServices = util.getParserServices(context, true);
+
     return {
+      'LogicalExpression[operator="||"], LogicalExpression[operator="??"]'(
+        node: TSESTree.LogicalExpression,
+      ): void {
+        const leftNode = node.left;
+        const rightNode = node.right;
+        const parentNode = node.parent;
+        const isRightNodeAnEmptyObjectLiteral =
+          rightNode.type === AST_NODE_TYPES.ObjectExpression &&
+          rightNode.properties.length === 0;
+        if (
+          !isRightNodeAnEmptyObjectLiteral ||
+          !parentNode ||
+          parentNode.type !== AST_NODE_TYPES.MemberExpression ||
+          parentNode.optional
+        ) {
+          return;
+        }
+
+        function isLeftSideLowerPrecedence(): boolean {
+          const logicalTsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
+
+          const leftTsNode = parserServices.esTreeNodeToTSNodeMap.get(leftNode);
+          const operator = isBinaryExpression(logicalTsNode)
+            ? logicalTsNode.operatorToken.kind
+            : ts.SyntaxKind.Unknown;
+          const leftPrecedence = util.getOperatorPrecedence(
+            leftTsNode.kind,
+            operator,
+          );
+
+          return leftPrecedence < util.OperatorPrecedence.LeftHandSide;
+        }
+        context.report({
+          node: parentNode,
+          messageId: 'optionalChainSuggest',
+          suggest: [
+            {
+              messageId: 'optionalChainSuggest',
+              fix: (fixer): TSESLint.RuleFix => {
+                const leftNodeText = sourceCode.getText(leftNode);
+                // Any node that is made of an operator with higher or equal precedence,
+                const maybeWrappedLeftNode = isLeftSideLowerPrecedence()
+                  ? `(${leftNodeText})`
+                  : leftNodeText;
+                const propertyToBeOptionalText = sourceCode.getText(
+                  parentNode.property,
+                );
+                const maybeWrappedProperty = parentNode.computed
+                  ? `[${propertyToBeOptionalText}]`
+                  : propertyToBeOptionalText;
+                return fixer.replaceTextRange(
+                  parentNode.range,
+                  `${maybeWrappedLeftNode}?.${maybeWrappedProperty}`,
+                );
+              },
+            },
+          ],
+        });
+      },
       [[
         'LogicalExpression[operator="&&"] > Identifier',
         'LogicalExpression[operator="&&"] > MemberExpression',
diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts
index a83198807a67..b2932466388d 100644
--- a/packages/eslint-plugin/src/util/index.ts
+++ b/packages/eslint-plugin/src/util/index.ts
@@ -4,6 +4,7 @@ export * from './astUtils';
 export * from './collectUnusedVariables';
 export * from './createRule';
 export * from './getFunctionHeadLoc';
+export * from './getOperatorPrecedence';
 export * from './getThisExpression';
 export * from './getWrappingFixer';
 export * from './misc';
diff --git a/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts b/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts
index d6ac19abb896..2b004e9d7a9c 100644
--- a/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts
+++ b/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts
@@ -146,6 +146,22 @@ const baseCases = [
 
 ruleTester.run('prefer-optional-chain', rule, {
   valid: [
+    'foo || {};',
+    'foo || ({} as any);',
+    '(foo || {})?.bar;',
+    '(foo || { bar: 1 }).bar;',
+    '(undefined && (foo || {})).bar;',
+    'foo ||= bar;',
+    'foo ||= bar || {};',
+    'foo ||= bar?.baz;',
+    'foo ||= bar?.baz || {};',
+    'foo ||= bar?.baz?.buzz;',
+    '(foo1 ? foo2 : foo3 || {}).foo4;',
+    '(foo = 2 || {}).bar;',
+    'func(foo || {}).bar;',
+    'foo ?? {};',
+    '(foo ?? {})?.bar;',
+    'foo ||= bar ?? {};',
     'foo && bar;',
     'foo && foo;',
     'foo || bar;',
@@ -501,5 +517,631 @@ foo?.bar(/* comment */a,
         },
       },
     },
+    {
+      code: '(foo || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 16,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(foo || ({})).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 18,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(await foo || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 22,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(await foo)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo1?.foo2 || {}).foo3;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 24,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo1?.foo2?.foo3;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((() => foo())() || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 28,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(() => foo())()?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: 'const foo = (bar || {}).baz;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 13,
+          endColumn: 28,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'const foo = bar?.baz;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo.bar || {})[baz];',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 21,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo.bar?.[baz];',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((foo1 || {}).foo2 || {}).foo3;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 31,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo1 || {}).foo2?.foo3;',
+            },
+          ],
+        },
+        {
+          messageId: 'optionalChainSuggest',
+          column: 2,
+          endColumn: 19,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo1?.foo2 || {}).foo3;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo || undefined || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo || undefined)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo() || bar || {}).baz;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 25,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo() || bar)?.baz;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((foo1 ? foo2 : foo3) || {}).foo4;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 34,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo1 ? foo2 : foo3)?.foo4;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`if (foo) { (foo || {}).bar; }`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 12,
+          endColumn: 27,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: noFormat`if (foo) { foo?.bar; }`,
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`if ((foo || {}).bar) { foo.bar; }`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 5,
+          endColumn: 20,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: noFormat`if (foo?.bar) { foo.bar; }`,
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(undefined && foo || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 29,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(undefined && foo)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo ?? {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 16,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(foo ?? ({})).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 18,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(await foo ?? {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 22,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(await foo)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo1?.foo2 ?? {}).foo3;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 24,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo1?.foo2?.foo3;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((() => foo())() ?? {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 28,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(() => foo())()?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: 'const foo = (bar ?? {}).baz;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 13,
+          endColumn: 28,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'const foo = bar?.baz;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo.bar ?? {})[baz];',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 21,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: 'foo.bar?.[baz];',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((foo1 ?? {}).foo2 ?? {}).foo3;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 31,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo1 ?? {}).foo2?.foo3;',
+            },
+          ],
+        },
+        {
+          messageId: 'optionalChainSuggest',
+          column: 2,
+          endColumn: 19,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo1?.foo2 ?? {}).foo3;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo ?? undefined ?? {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo ?? undefined)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo() ?? bar ?? {}).baz;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 25,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo() ?? bar)?.baz;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((foo1 ? foo2 : foo3) ?? {}).foo4;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 34,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo1 ? foo2 : foo3)?.foo4;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`if (foo) { (foo ?? {}).bar; }`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 12,
+          endColumn: 27,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: noFormat`if (foo) { foo?.bar; }`,
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`if ((foo ?? {}).bar) { foo.bar; }`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 5,
+          endColumn: 20,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: noFormat`if (foo?.bar) { foo.bar; }`,
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(undefined && foo ?? {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 29,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(undefined && foo)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(a > b || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 18,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(a > b)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`(((typeof x) as string) || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 35,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: noFormat`((typeof x) as string)?.bar;`,
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(void foo() || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 23,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(void foo())?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '((a ? b : c) || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 24,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(a ? b : c)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`((a instanceof Error) || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 33,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(a instanceof Error)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`((a << b) || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 21,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(a << b)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: noFormat`((foo ** 2) || {}).bar;`,
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 23,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo ** 2)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo ** 2 || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 21,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo ** 2)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(foo++ || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 18,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(foo++)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
+    {
+      code: '(+foo || {}).bar;',
+      errors: [
+        {
+          messageId: 'optionalChainSuggest',
+          column: 1,
+          endColumn: 17,
+          suggestions: [
+            {
+              messageId: 'optionalChainSuggest',
+              output: '(+foo)?.bar;',
+            },
+          ],
+        },
+      ],
+    },
   ],
 });