microsoft / microsoft/TypeScript
Dynamic object key + discriminated union + typeof could have a better narrowing type
Nessuno ha ancora preso questa issue.
- Lingua principale
- Go
- Stelle
- 111k
- Fork
- 14.3k
- Merge medio
- 2g 4h
- PR unite (30g)
- 132
Descrizione
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
}
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Direzione di ricerca
Inizia dagli esempi collegati di TypeScript Playground e confronta i risultati attuali del narrowing con i risultati richiesti per i controlli string, object e typeof impossibili. L'attività è completata quando il valore della discriminated union viene ristretto al membro appropriato, oppure a never nel caso impossibile, inclusi gli esempi con chiave dinamica e proprietà esplicita.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- typescript
- Ambito
- compilers
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100