microsoft / microsoft/TypeScript
Dynamic object key + discriminated union + typeof could have a better narrowing type
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.4k
- Merge medio
- 1 d 19 h
- PR fusionados (30 d)
- 117
Descripción
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
}
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con los ejemplos vinculados de TypeScript Playground y compara los resultados actuales de narrowing con los resultados solicitados para las comprobaciones de string, object y typeof imposibles. La tarea estará terminada cuando el valor de la unión discriminada se reduzca al miembro adecuado o a never en el caso imposible, incluidos los ejemplos de clave dinámica y propiedad explícita.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- compilers
- Tipo de issue
- Nueva funcionalidad
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 35/100