Repository: TypeScript
Issue: Variables that are used-before-assigned are typed without `undefined`
Labels: Suggestion,Awaiting More Feedback

# 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.
-->
variable use before assign

### 🕗 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 the behavior in every version I tried

### ⏯ 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/DYUwLgBAHlBcEDsCuBbARiATgbgFC4migDowB7AMQEsoQATACgEo8B6ViAPQH5d2IwATwAOIMgDMiEALyzEqDJgiAZcnyhIgwQEJ4ydFjwEIm0pRr1mbDjz4choiccEy5exRECg5EA)

### 💻 Code

<!-- Please post the relevant code sample here as well-->
```ts
let xx: number;

  xx.toFixed();
// ^?
// typeof xx === number ❌

let yy!: number;

  yy.toFixed();
// ^?
// typeof yy === number ✅
```

### 🙁 Actual behavior

<!-- What happened, and why it was wrong -->
TS reports the type of the used-before-assigned variable `xx` as `number`, and reports error `Variable 'xx' is used before being assigned. (2454)`

### 🙂 Expected behavior

<!-- What you expected to happen instead, and why -->
TS reports the type of `xx` as `number | undefined`.

### Additional info

This behaviour makes it difficult for us to write lint rules because when we attempt to check if the variable is `undefined`, the type system reports that it is not.

Examples:
- checking for unnecessary conditions based on types
    - `if (xx != null) {}` The types say `xx` is `number`, so `!= null` looks like it's unnecessary.
- checking for unnecessary type assertions
    - `xx!` Again the types say `xx` is `number`, so the non-null assertion looks like it's unnecessary.

Example issue:
- https://github.com/typescript-eslint/typescript-eslint/issues/453
- https://github.com/typescript-eslint/typescript-eslint/issues/6640

[In the past we've manually coded up logic to do used-before-assigned checks](https://github.com/typescript-eslint/typescript-eslint/blob/a1a20b3fd12ce47d3c98fea53314ea14b42eeec1/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts#L91-L125) where necessary - but it's pretty gnarly code to maintain and we have to ensure that we cover this case in our implementation.

It would be great if TS reported the "correct" type here with `undefined`.