diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index ac4f95611316a..b3a99be4155c1 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -22763,6 +22763,10 @@ namespace ts {
                         getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) :
                         leftType;
                 case SyntaxKind.BarBarToken:
+                    leftType = leftType.flags & TypeFlags.IndexedAccess ?
+                        any(getPropertiesOfType((<IndexedAccessType>leftType).objectType), prop => !!(prop.flags & SymbolFlags.Optional)) ?
+                            neverType : leftType :
+                        leftType;
                     return getTypeFacts(leftType) & TypeFacts.Falsy ?
                         getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], UnionReduction.Subtype) :
                         leftType;
diff --git a/src/compiler/core.ts b/src/compiler/core.ts
index a2f2b24550207..3d5897ae84474 100644
--- a/src/compiler/core.ts
+++ b/src/compiler/core.ts
@@ -232,6 +232,18 @@ namespace ts {
         return undefined;
     }
 
+    /**
+     * Returns true if any of the items in array satisfies predicate 'if provided' or is truthy
+     */
+    export function any<T>(array: ReadonlyArray<T>, predicate?: (i: any) => boolean): boolean {
+        for (const item of array) {
+            if (!predicate ? item : predicate(item)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     export function firstDefinedIterator<T, U>(iter: Iterator<T>, callback: (element: T) => U | undefined): U | undefined {
         while (true) {
             const { value, done } = iter.next();
diff --git a/tests/baselines/reference/shortCircuitEvaluation.js b/tests/baselines/reference/shortCircuitEvaluation.js
new file mode 100644
index 0000000000000..3d0f0bf351020
--- /dev/null
+++ b/tests/baselines/reference/shortCircuitEvaluation.js
@@ -0,0 +1,28 @@
+//// [shortCircuitEvaluation.ts]
+let a = undefined || 1;
+a++
+
+let b = null || 'foo';
+b.concat('bar')
+
+type EventType = 'click' | 'dblclick'
+
+const handlerMap: { [P in EventType]?: any[] } = {}
+
+function addHandler<P extends EventType>(evType: P) {
+  const handlerList = handlerMap[evType] || <any[]>[]
+  handlerList.push({})
+  handlerMap[evType] = handlerList
+}
+
+//// [shortCircuitEvaluation.js]
+var a = undefined || 1;
+a++;
+var b = null || 'foo';
+b.concat('bar');
+var handlerMap = {};
+function addHandler(evType) {
+    var handlerList = handlerMap[evType] || [];
+    handlerList.push({});
+    handlerMap[evType] = handlerList;
+}
diff --git a/tests/baselines/reference/shortCircuitEvaluation.symbols b/tests/baselines/reference/shortCircuitEvaluation.symbols
new file mode 100644
index 0000000000000..123afe2520cf2
--- /dev/null
+++ b/tests/baselines/reference/shortCircuitEvaluation.symbols
@@ -0,0 +1,46 @@
+=== tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/shortCircuitEvaluation.ts ===
+let a = undefined || 1;
+>a : Symbol(a, Decl(shortCircuitEvaluation.ts, 0, 3))
+>undefined : Symbol(undefined)
+
+a++
+>a : Symbol(a, Decl(shortCircuitEvaluation.ts, 0, 3))
+
+let b = null || 'foo';
+>b : Symbol(b, Decl(shortCircuitEvaluation.ts, 3, 3))
+
+b.concat('bar')
+>b.concat : Symbol(String.concat, Decl(lib.es5.d.ts, --, --))
+>b : Symbol(b, Decl(shortCircuitEvaluation.ts, 3, 3))
+>concat : Symbol(String.concat, Decl(lib.es5.d.ts, --, --))
+
+type EventType = 'click' | 'dblclick'
+>EventType : Symbol(EventType, Decl(shortCircuitEvaluation.ts, 4, 15))
+
+const handlerMap: { [P in EventType]?: any[] } = {}
+>handlerMap : Symbol(handlerMap, Decl(shortCircuitEvaluation.ts, 8, 5))
+>P : Symbol(P, Decl(shortCircuitEvaluation.ts, 8, 21))
+>EventType : Symbol(EventType, Decl(shortCircuitEvaluation.ts, 4, 15))
+
+function addHandler<P extends EventType>(evType: P) {
+>addHandler : Symbol(addHandler, Decl(shortCircuitEvaluation.ts, 8, 51))
+>P : Symbol(P, Decl(shortCircuitEvaluation.ts, 10, 20))
+>EventType : Symbol(EventType, Decl(shortCircuitEvaluation.ts, 4, 15))
+>evType : Symbol(evType, Decl(shortCircuitEvaluation.ts, 10, 41))
+>P : Symbol(P, Decl(shortCircuitEvaluation.ts, 10, 20))
+
+  const handlerList = handlerMap[evType] || <any[]>[]
+>handlerList : Symbol(handlerList, Decl(shortCircuitEvaluation.ts, 11, 7))
+>handlerMap : Symbol(handlerMap, Decl(shortCircuitEvaluation.ts, 8, 5))
+>evType : Symbol(evType, Decl(shortCircuitEvaluation.ts, 10, 41))
+
+  handlerList.push({})
+>handlerList.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
+>handlerList : Symbol(handlerList, Decl(shortCircuitEvaluation.ts, 11, 7))
+>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
+
+  handlerMap[evType] = handlerList
+>handlerMap : Symbol(handlerMap, Decl(shortCircuitEvaluation.ts, 8, 5))
+>evType : Symbol(evType, Decl(shortCircuitEvaluation.ts, 10, 41))
+>handlerList : Symbol(handlerList, Decl(shortCircuitEvaluation.ts, 11, 7))
+}
diff --git a/tests/baselines/reference/shortCircuitEvaluation.types b/tests/baselines/reference/shortCircuitEvaluation.types
new file mode 100644
index 0000000000000..9142a4708e208
--- /dev/null
+++ b/tests/baselines/reference/shortCircuitEvaluation.types
@@ -0,0 +1,58 @@
+=== tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/shortCircuitEvaluation.ts ===
+let a = undefined || 1;
+>a : number
+>undefined || 1 : 1
+>undefined : undefined
+>1 : 1
+
+a++
+>a++ : number
+>a : number
+
+let b = null || 'foo';
+>b : string
+>null || 'foo' : "foo"
+>null : null
+>'foo' : "foo"
+
+b.concat('bar')
+>b.concat('bar') : string
+>b.concat : (...strings: string[]) => string
+>b : string
+>concat : (...strings: string[]) => string
+>'bar' : "bar"
+
+type EventType = 'click' | 'dblclick'
+>EventType : EventType
+
+const handlerMap: { [P in EventType]?: any[] } = {}
+>handlerMap : { click?: any[] | undefined; dblclick?: any[] | undefined; }
+>{} : {}
+
+function addHandler<P extends EventType>(evType: P) {
+>addHandler : <P extends EventType>(evType: P) => void
+>evType : P
+
+  const handlerList = handlerMap[evType] || <any[]>[]
+>handlerList : any[]
+>handlerMap[evType] || <any[]>[] : any[]
+>handlerMap[evType] : { click?: any[] | undefined; dblclick?: any[] | undefined; }[P]
+>handlerMap : { click?: any[] | undefined; dblclick?: any[] | undefined; }
+>evType : P
+><any[]>[] : any[]
+>[] : never[]
+
+  handlerList.push({})
+>handlerList.push({}) : number
+>handlerList.push : (...items: any[]) => number
+>handlerList : any[]
+>push : (...items: any[]) => number
+>{} : {}
+
+  handlerMap[evType] = handlerList
+>handlerMap[evType] = handlerList : any[]
+>handlerMap[evType] : { click?: any[] | undefined; dblclick?: any[] | undefined; }[P]
+>handlerMap : { click?: any[] | undefined; dblclick?: any[] | undefined; }
+>evType : P
+>handlerList : any[]
+}
diff --git a/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/shortCircuitEvaluation.ts b/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/shortCircuitEvaluation.ts
new file mode 100644
index 0000000000000..f2ee19e655bee
--- /dev/null
+++ b/tests/cases/conformance/expressions/binaryOperators/logicalOrOperator/shortCircuitEvaluation.ts
@@ -0,0 +1,16 @@
+// @strictNullChecks: true
+let a = undefined || 1;
+a++
+
+let b = null || 'foo';
+b.concat('bar')
+
+type EventType = 'click' | 'dblclick'
+
+const handlerMap: { [P in EventType]?: any[] } = {}
+
+function addHandler<P extends EventType>(evType: P) {
+  const handlerList = handlerMap[evType] || <any[]>[]
+  handlerList.push({})
+  handlerMap[evType] = handlerList
+}
\ No newline at end of file