microsoft / microsoft/TypeScript
Compilation option: `stricterPropertyInitialization`
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 1日 19時間
- マージ済み PR(30日)
- 117
説明
🔍 Search Terms
Keywords: "stricter property initiazliation"
✅ Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- 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:
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.
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:
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:
class UserAccount {
// ...
address: string | undefined = undefined;
constructor(name: string) {
this.name = name;
}
}
💻 Use Cases
-
What do you want to use this for?
A high-performance TS/JS library -
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. -
What workarounds are you using in the meantime?
Vigilance
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
この issue にはファイル、テスト、エントリポイントが記載されていません。まず strictPropertyInitialization の実装とテストを見つけ、次に、| undefined 型の未初期化フィールドを明示的に初期化されたフィールドと比べて、別のオプションでどのように扱うべきかを決定してください。新しいオプションの動作と名前が確定し、UserAccount の例が compiler tests でカバーされれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100