microsoft / microsoft/TypeScript
Narrow object property indexed by bracket notation when the key is a known literal type, regardless of where the key comes from
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.3k
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 132
説明
🔍 Search Terms
type guard, narrowing, control flow analysis, property, index, known type, literal type, bracket notation
✅ 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
This is a different re-opening or re-focusing of #10530, not the same as #56389, and was not fixed by #57847. The original motivating example for #10530 (treat obj["key"] like obj.key for narrowing) was fixed long ago, and more recently many of the remaining requests which had been added to #10530 were also fixed (narrowing for obj[key] when key is a variable whose literal type isn't known, for multiple uses of the same key). Those issues are closed. But it seems there are still some issues lumped in with #10530 which were not addressed, so here's the suggestion:
Please enable narrowing of object properties accessed via bracket notation based on the type of the key whenever the key's type is a known literal, even if multiple distinct variables or properties are used as keys. That is, if you have key1 and key2 and keyObj.prop and they are all of the literal type "foo" (or have been narrowed to that type), then treat obj[key1] and obj[key2] and obj[keyObj.prop] all as obj.foo for control flow purposes.
📃 Motivating Example
#51368 gives one, where the variable is a let variable annotated with a literal type or const asserted :
let k: "foo" = "foo";
// let k = "foo" as const; // <-- same behavior
const obj = { foo: Math.random() < 0.5 ? "abc" : undefined }
if (obj.foo) { obj[k].toUpperCase() } // error!
// ~~~~~~ possibly undefined
Probably I'd say someone should use a const there instead of let.
There's also one from this Stack Overflow question, involving enum-like const-asserted objects:
const Enum = { FOO: "foo", BAR: "bar" } as const;
const obj = { [Enum.FOO]: Math.random() < 0.5 ? "abc" : undefined }
if (obj[Enum.FOO]) obj[Enum.FOO].toUpperCase() // ERROR!
// ~~~~~~~~~~~~~ possibly undefined
This one strikes me as quite unfortunate, since an actual enum works just fine here:
enum Enum { FOO = "foo", BAR = "bar" }
const obj = { [Enum.FOO]: Math.random() < 0.5 ? "abc" : undefined }
if (obj[Enum.FOO]) obj[Enum.FOO].toUpperCase() // OKAY
💻 Use Cases
- What do you want to use this for?
See #10530 and various issues closed as duplicates for more use cases.
- Current approaches and workarounds:
If TS knows the literal key then you do too, so you could always just use it directly:
const Enum = { FOO: "foo", BAR: "bar" } as const;
const obj = { [Enum.FOO]: Math.random() < 0.5 ? "abc" : undefined }
if (obj.foo) obj.foo.toUpperCase() // OKAY
That's reasonable, but I think it would be nice if there weren't this caveat for enum-like objects where you can't actually use them as keys directly for narrowing purposes.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
リンクされている TypeScript Playground の例から始め、残りの挙動を issue #10530、#56389、#57847 と比較してください。望ましい結果は、キーが同じ既知のリテラル型を持つブラケットアクセスが、ドットプロパティアクセスと同様に絞り込まれることです。これには let キーと enum のような const オブジェクトの例も含まれます。実装ファイルやテストは指定されていません。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100