microsoft / microsoft/TypeScript

Dynamic object key + discriminated union + typeof could have a better narrowing type

Abierto
#37,465 0 comentarios 5 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Awaiting More Feedback Suggestion
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
}

Full code on playground

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"
}

Playground

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

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. 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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.