Repository: TypeScript
Issue: explicit type narrowing is not working
Labels: Bug

# Bug Report

<!--
  Please fill in each section completely. Thank you!
-->

### 🔎 Search Terms

<!--
  What search terms did you use when trying to find an existing bug report?
  List them here so people in the future can find this one more easily.
-->
`explicit type narrowing` `type narrowing by value`

### 🕗 Version & Regression Information

<!-- When did you start seeing this bug occur?

"Bugs" that have existed in TS for a long time are very likely to be FAQs; refer to
  https://github.com/Microsoft/TypeScript/wiki/FAQ#common-bugs-that-arent-bugs

If possible, please try testing the nightly version of TS to see if it's already been fixed.
For npm: `typescript@next`
This is also the 'Nightly' version in the playground: http://www.typescriptlang.org/play/?ts=Nightly

Note: The TypeScript Playground can be used to try older versions of TypeScript.

Please keep and fill in the line that best applies:
-->
- This is a crash
- This changed between versions ______ and _______
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________
- I was unable to test this on prior versions because _______

### ⏯ Playground Link

<!--
  A link to a TypeScript Playground "Share" link which shows this behavior

  The TypeScript Workbench can be used for more complex setups, try
  https://www.typescriptlang.org/dev/bug-workbench/

  As a last resort, you can link to a repo, but these will be slower for us to investigate.
-->
[Playground link with relevant code](https://www.typescriptlang.org/play?#code/C4TwDgpgBAgmCWAlCBnMB7Adi6BeKA3gFBSlQoCuAxlaigFxTABOFEANCWQCYCGwvRihbxMAcyIBfIkVCRYCAKLNm6ZlHzEyUeCmWrmjFm07aIKtY31qpMgPR2oAOXTAoAGyxjzUAO5qAa1EJKixhKGYIAEc2cPxeFBBMKigACgBKRgAFVQBbXQgAHjgkVAxsCAA+DWqtMlDsN0i0MIhGEuQWiqgAHwV4a3V43154NwJyaloUBiZWDig+AUYAcgALCHdPFahJKAT9zBAAbi5SeAAzNObynCgAMnumcAh0K5vWjVx8FfQAIwAVhAqMAdo8oCtdIMdqIImVPuCPhUAHRQizMdKEM7aOFdHDY7TANaqXy424QZHmAzY6TYyLACjMTBk1q2IgOKAAdUCwT8YzW6AobiJ0GMRNEdCgVA2VACOmw8G4oo2Uqw3DG8CwRAa4UiMVQwAATBp9olkmlMlAcuh8jhighOuTqrhatidU14RV2g7PXc+iVBibeCMxoRJjQ6EZ5uxFvxBBCNlt0Ds9gdeEdTtpLtdfdBwXJXu9c18fv8gSCwU9IXp0TDmUicJi6jiWRUCWQiSTWzhKeiaTJtPTGfXc7YgA)

### 💻 Code

<!-- Please post the relevant code sample here as well-->
```ts
type ApiResponse = {
    success: true,
    data: string
}

type ApiError = {
    isError: true,
    error: Error
}

// Not longer working
const request = async (): Promise<ApiResponse> => {
    const response: ApiResponse | ApiError = await { success: true, data: 'hello' } as any;
    if (response && typeof response === 'object' && 'isError' in response && response.isError) {
        response
        throw response.error
    }

    return response
}

// Working without the truthiness check inside the condition
const request2 = async (): Promise<ApiResponse> => {
    const response: ApiResponse | ApiError = await { success: true, data: 'hello' } as any;
    if (response && typeof response === 'object' && 'isError' in response) {
        response
        throw response.error
    }

    return response
}
```

### 🙁 Actual behavior

<!-- What happened, and why it was wrong -->
TS is complaining in line 19 about unassignable types becauce it thinks the responce can be an ApiError but it technically cant because of the if block and throw statement.
The interesting thing is, if I omit the response.isError truthiness check, the code is working. Obviously typescript is thinking about of `isError` can be a boolean, but by definition it always can have the value `true`.

### 🙂 Expected behavior
In this case I expect, typescript can narrow down the type in the if statement to ApiResponse and knows after the if statement the response can only be of type ApiResponse.
<!-- What you expected to happen instead, and why -->