Repository: TypeScript
Issue: Compilation option: `stricterPropertyInitialization`
Labels: Suggestion,Awaiting More Feedback

### 🔍 Search Terms

Keywords: "stricter property initiazliation"

### ✅ Viability Checklist

- [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
- [x] This wouldn't change the runtime behavior of existing JavaScript code
- [x] This could be implemented without emitting different JS based on the types of the expressions
- [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- [x] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- [x] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

### ⭐ Suggestion

So, TypeScript offers the `strictPropertyInitialization` compiler option, which is helpful, but it has this behavior:
```ts
class UserAccount {
  name: string; // not an error, initialized in constructor
  accountType = "user"; // initialized
 
  email: string; // this is an error
  address: string | undefined; // NOT an error but ALSO not technically initialized!
 
  constructor(name: string) {
    this.name = name;
  }
}
```
This is great except for one thing: performance. Uninitialized properties in the class (specifically: `address`) will, at least in V8, potentially switch the class to dictionary mode vs struct mode when the property eventually gets assigned, leading to slower read/writes. This was confirmed by a V8 developer in [this StackOverflow thread](https://stackoverflow.com/questions/24987896/how-does-bluebirds-util-tofastproperties-function-make-an-objects-properties). 

So the suggestion is that `stricterPropertyInitialization` sets `strictPropertyInitialization` to `true` AND throws an error if the author has added `| undefined` to the type to implicity define the type. In other words, "strict property initialization" would mean what it says: strict property initialization. If it is not initialized, it is an error. In the above example, from the tsconfig docs, the `address` is not initialized. It's too late to change that as default behavior, hence the additional flag.

_Note: maybe `stricterPropertyInitialization` is too awkward? Something like `disallowImplicitUndefinedClassFields`? 🤷‍♂_

### 📃 Motivating Example

Most devs probably won't need to worry about the performance implications of internal dictionary vs. struct. In my case, in the library I'm maintaining / working on, every millisecond / fraction of a millisecond counts, so I'm trying to determine the fastest path in every scenario. I expected `strictPropertyInitialization` to mean what it says to prevent properties from not being initialized and avoid any accidental performance pitfalls from non-initialization, but it doesn't. 🤷‍♂ 

Meaning, in the above example:
```ts
class UserAccount {
  name: string; // not an error, initialized in constructor
  accountType = "user"; // initialized
 
  email: string; // this is an error
  address: string | undefined; // NOT an error but ALSO not technically initialized!
 
  constructor(name: string) {
    this.name = name;
  }

  someMethod() {
    // The class will now possible de-optimize its performance to Dictionary mode, since V8
    // thinks that the object needs to have arbitrary properties added. It doesn't know about `address`
    this.address = '123 fake street' 
  }
}
```

So, most simply, `stricterPropertyInitialization` would throw a compilation error if `| undefined` is added to a property and the property is not explicitly initialized with a field initializer or in the constructor.

If the code author wishes to _actually_ initialize the field, to undefined, it must be something like:
```ts
class UserAccount {
  // ...
  address: string | undefined = undefined;
 
  constructor(name: string) {
    this.name = name;
  }
}
```

### 💻 Use Cases

1. What do you want to use this for?
A high-performance TS/JS library

2. What shortcomings exist with current approaches?
There are no workarounds as far as I know. You simply have to let all devs on your team know to not write this and hope people catch it.

3. What workarounds are you using in the meantime?
Vigilance