microsoft / microsoft/TypeScript
Dynamic object key + discriminated union + typeof could have a better narrowing type
まだ誰も着手していません。
- 主要言語
- Go
- スター
- 111k
- フォーク
- 14.4k
- 平均マージ
- 1日 19時間
- マージ済み PR(30日)
- 117
説明
Search Terms
dynamic object key, discriminated union, typeof, type inference, narrowing type
Suggestion (or is it a bug report?)
We could write a discriminated union with one of the cases is a dynamic object key. For example...
type TExample = (
{
[key in string]: {
foo: number
}
}
| {
errorCode: string
}
)
So, if the key is errorCode it could be a { foo: number } or a string. If the key is any string that isn't errorCode, it should be a { foo: number }.
Then let's check that.
const func: () => TExample = () => ... // get value from somewhere
const value = func()
if ('errorCode' in value && typeof value.errorCode === 'string') {
value // what's the type of value here?
}
So, makes sense that the value's type should be { errorCode: string }, right?
But the type still is TExample! I think that we could have a better narrowing type, because value only shoud be { errorCode: string } on this case.
Similarly, would be nice to have that:
if ('errorCode' in value && typeof value.errorCode === 'object') {
value // should be { [key in string]: { foo: number } }
}
As well as...
if ('errorCode' in value && typeof value.errorCode === 'number') {
value // should be never
}
Edit
I just noticed that it happens even when we are not using a dynamic object key...
type TExample = (
{
aaa: {
foo: number
}
}
| {
errorCode: string
}
)
const func: () => TExample = () => ... // get value from somewhere
const value = func()
if ('errorCode' in value && ((typeof value.errorCode) === 'number')) {
value // type is "{ errorCode: string }" ...... what!? I think that the expected is to be "never"
}
Use Cases
I'm opening this issue because I had a problem because of this limitation.
I'm developing a client for an API and, for convention, all errors is returned as { errorCode: string }.
And on an endpoint, the json can be a { [key in string]: TComplexObject } on success case, or be a { errorCode: string } on fail case.
So normally I'm checking if I had an error using if ('errorCode' in result) {, but on this endpoint it isn't enough since we have this limitation on TS. Then I don't have a good type inference on this case, needing to write a more complex code.
Examples
type TExample = (
{
[key in string]: {
foo: number
}
}
| {
errorCode: string
}
)
const func: () => TExample = () => ({ blah: { foo: 1 } })
const value = func()
if ('errorCode' in value && typeof value.errorCode === 'string') {
value // should be { errorCode: string }
}
if ('errorCode' in value && typeof value.errorCode === 'object') {
value // should be { [key in string]: { foo: number } }
}
if ('errorCode' in value && typeof value.errorCode === 'number') {
value // should be never
}
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
リンクされている TypeScript Playground の例から始め、string、object、および不可能な typeof チェックについて、現在の絞り込み結果を要求された結果と比較します。完了条件は、判別共用体の値が適切なメンバーに、または不可能なケースでは never に絞り込まれることです。動的キーと明示的プロパティの例も含みます。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- typescript
- 領域
- compilers
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100