microsoft / microsoft/TypeScript

Incorrect error attribution on indexed access, when using object spread operator

Abierto
#60,675 5 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Domain: Indexed Access Types Help Wanted Possible Improvement
Lenguaje dominante
Go
Estrellas
111k
Forks
14.4k
Merge medio
1 d 19 h
PR fusionados (30 d)
117

Descripción

🔎 Search Terms

spread operator destructuring error, spread error message, object indexed access error message

🕗 Version & Regression Information
⏯ Playground Link

Playground link, 5.7.2

💻 Code
type EventPayloads = {
    completeSprint: {
        automationId: string,
        spaceId: string,
    },
    sendMessage: {
        message: string,
    },
}

type CompletedEvent<T extends keyof EventPayloads> = {
    [E in T]: {
        type: E,
        payload: EventPayloads[E],
        appName: string,
    }
}[T]

function overwriteAppName<T extends keyof EventPayloads>(
    scheduled: CompletedEvent<T>,
): CompletedEvent<T> {
    const { appName, ...rest } = scheduled
    // Weird error message here, starting in 4.3
    return {
        ...rest,
        appName: "test",
    }
}
🙁 Actual behavior

The return statement has the following error:

Type 'Omit<CompletedEvent<T>, "appName"> & { appName: string; }' is not assignable to type 'CompletedEvent<T>'.
  Types of property 'payload' are incompatible.
    Type 'CompletedEvent<T>["payload"]' is not assignable to type 'EventPayloads[T]'.
      Type '{ type: T; payload: EventPayloads[T]; appName: string; }' is missing the following properties from type 'EventPayloads': completeSprint, sendMessage(2322)

The first three lines make sense, but the last line is bizarre enough that I suspect it's a bug in either the reporting/checking logic.

Given that EventPayloads and CompletedEvent are completely different objects, this error made me think I had missed an indexing step somewhere, but after rereading the code multiple times I'm pretty sure I didn't (it seems like a type error in the type error).

Also, my best possible explanation for the reduction in this step

    Type 'CompletedEvent<T>["payload"]' is not assignable to type 'EventPayloads[T]'.
      Type '{ type: T; payload: EventPayloads[T]; appName: string; }' is missing the following properties from type 'EventPayloads': completeSprint, sendMessage(2322)

is that the algorithm eliminated the indexed access on both sides, so that

CompletedEvent<T>["payload"] EventPayloads[T]
becomes CompletedEvent<T> EventPayloads

but this is clearly incorrect considering T != "payload".

🙂 Expected behavior

Given the penultimate line of the error, I would expect the final line to compare payload types, i.e. { automationId: string, spaceId: string } vs. { message: string }

For what it's worth, this is the error from 4.2.3 and earlier:
Type 'Omit<CompletedEvent<T>, "appName"> & { appName: string; }' is not assignable to type 'CompletedEvent<T>'.
  Types of property 'payload' are incompatible.
    Type 'CompletedEvent<T>["payload"]' is not assignable to type 'EventPayloads[T]'.
      Type '{ type: T; payload: EventPayloads[T]; appName: string; }' is missing the following properties from type 'EventPayloads': completeSprint, sendMessage
        Type 'CompletedEvent<T>["payload"]' is not assignable to type '{ automationId: string; spaceId: string; } & { message: string; }'.
          Type 'EventPayloads[T]' is not assignable to type '{ automationId: string; spaceId: string; } & { message: string; }'.
            Type '{ automationId: string; spaceId: string; } | { message: string; }' is not assignable to type '{ automationId: string; spaceId: string; } & { message: string; }'.
              Type '{ automationId: string; spaceId: string; }' is not assignable to type '{ automationId: string; spaceId: string; } & { message: string; }'.
                Property 'message' is missing in type '{ automationId: string; spaceId: string; }' but required in type '{ message: string; }'.
                  Type 'EventPayloads[T]' is not assignable to type '{ automationId: string; spaceId: string; }'.
                    Type 'CompletedEvent<T>["payload"]' is not assignable to type '{ automationId: string; spaceId: string; }'.
                      Type 'EventPayloads[T]' is not assignable to type '{ automationId: string; spaceId: string; }'.
                        Type '{ automationId: string; spaceId: string; } | { message: string; }' is not assignable to type '{ automationId: string; spaceId: string; }'.
                          Type '{ message: string; }' is missing the following properties from type '{ automationId: string; spaceId: string; }': automationId, spaceId(2322)
Additional information about the issue

I've tagged the issue with object spread operator because removing the spreads resolves the error. But I don't actually know whether the bug is intrinsic to spreads.

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

Reproduce el diagnóstico en el TypeScript Playground enlazado usando las versiones 4.2.3, 4.3.5 y 5.7.2, y compáralo después con la variante sin spread. Sigue la ruta del checker que informa del desajuste de indexed access y añade una prueba de regresión; se considera terminado cuando el diagnóstico final conserva la comparación de payloads en lugar de referirse a EventPayloads como un todo.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
typescript
Área
compilers
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
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.