microsoft / microsoft/TypeScript

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

Aperta
#60,675 5 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Domain: Indexed Access Types Help Wanted Possible Improvement
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

🔎 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.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Riproduci la diagnostica nel TypeScript Playground collegato usando le versioni 4.2.3, 4.3.5 e 5.7.2, quindi confrontala con la variante senza spread. Segui il percorso del checker che segnala il mismatch dell'indexed access e aggiungi un test di regressione; il lavoro è concluso quando la diagnostica finale mantiene il confronto dei payload invece di riferirsi a EventPayloads nel suo complesso.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.