Repository: TypeScript
Issue: Check JS doesn't narrow types properly
Labels: Needs Investigation

<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨

Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker. Even if you think you've found a *bug*, please read the FAQ first, especially the Common "Bugs" That Aren't Bugs section!

Please help us by doing the following steps before logging an issue:
  * Search: https://github.com/Microsoft/TypeScript/search?type=Issues
  * Read the FAQ: https://github.com/Microsoft/TypeScript/wiki/FAQ

Please fill in the *entire* template below.
-->

<!--
Please try to reproduce the issue with the latest published version. It may have already been fixed.
For npm: `typescript@next`
This is also the 'Nightly' version in the playground: http://www.typescriptlang.org/play/?ts=Nightly
-->
**TypeScript Version:**  3.7.x-dev.201xxxxx

<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**

**Code**

```ts
import { useReducer } from 'react';

/**
 * @template {{ type: string; payload?: any; }} Action
 * @template {object} State
 * @template {{ past: State[]; present: State; future: State[]; }} UndoState
 * @template {{ type: 'UNDO'; } | { type: 'REDO'; }} UndoAction
 * @param {{ (state: State, action: Action): State; }} reducer
 * @param {State} initialState
 */
export function useUndoReducer(reducer, initialState) {
  /**
   * @param {UndoState} state
   * @param {UndoAction | Action} action
   */
  const undoReducer = (state, action) => {
    switch (action.type) {
      case 'UNDO': {
        const [newPresent, ...newPast] = state.past;

        return {
          past: newPast,
          present: newPresent,
          future: [state.present, ...state.future],
        };
      }
      case 'REDO': {
        const [newPresent, ...newFuture] = state.future;

        return {
          past: [state.present, ...state.past],
          present: newPresent,
          future: newFuture,
        };
      }
      default:
        return {
          past: [state.present, ...state.past],
          // @ts-ignore
          present: reducer(state.present, action),
          future: [],
        };
    }
  };

  return useReducer(undoReducer, {
    past: [],
    present: initialState,
    future: [],
  });
}
```

**Expected behavior:**

not having to use a `@ts-ignore`

**Actual behavior:**

had to use `@ts-ignore`

**Playground Link:** <!-- A link to a TypeScript Playground "Share" link which demonstrates this behavior -->

https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=51&pc=1&useJavaScript=true#code/JYWwDg9gTgLgBAbzgVwM4FMBK6AmyDG6UcAvnAGZQQhwDkU6AhvjLQNwBQHA9AFS8c4vOAAEY6cABtG4xEhgBPMOgBccVDCjAAdgHM2cMIwWSIjHAH41jbQoMkyAQRbAI2wcLESw02QggARgBW6CxkAMowMugeouJS0XKGjBpqkdEA2gC6BmAMGNowaVHiBuTIMMgMxZk5pGQAqto4EOnisV4JfvJKqnQNAHIAIgDy7KRwAD6IcIrKarSYAKKj4w5wTS3OMK7uQqJGUIw0CEgAFBrRNeIANHDMO25q27sAlNfo9mQMeIRQHYdjog2ugyDpgDtGJIQR5uBx0AAPSCwCjIbQuNwoDCbCDYX5EM4-AhEO7gyHQkroV6IQRwPgCOCMzyAk44kFkS7tRn7EQsxA4l6Y6aC7RkB67WlCOGM-BuDQoZq43DE4gAXjgF0pd3FbmpqoAfDTueoAO4Q-AACw1Ou0ADo5lSjca4PgUuh+sMxmoEJLnbLtPKMtp0CaAAr5dCFO62mPBsMpGBZODqznoW1GDScX3GhiVKDaJ3O7kZopwOOhhM3bPOvLoAql8sRqPV43lPN9DKp9NNmDRmNdttVdBZKtFxkkThFkjV10YOjLVbelsuuXwIMh8N1yO9uAx21xgBiFSHSZTlNtg4YWbHcFzVQLPpvjJLak759r9b7tq7JZHy+fPZqI2W7Nk+qLtkBIZHu2o5jhO1bTkWODoOQjDIJIRTLne+aFmOL5wG+0TdiBO57j+CZ-mBH7bmoRJ-JqRHUVG9wYtorywTel4dpRcGTtyiGkNet7oHmBZoFgyr0WiLR4iqdyPsWCavjxAEkWoZLAFCIIceBQ7KbBJCvJw05AA

**Related Issues:** <!-- Did you find other bugs that looked similar? -->