microsoft / microsoft/TypeScript

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

Offen
#60,675 5 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Domain: Indexed Access Types Help Wanted Possible Improvement
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

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

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Reproduziere die Diagnose im verlinkten TypeScript Playground mit den Versionen 4.2.3, 4.3.5 und 5.7.2 und vergleiche sie anschließend mit der Variante ohne Spread. Verfolge den Checker-Pfad, der den Indexed-Access-Mismatch meldet, und füge einen Regressionstest hinzu; abgeschlossen ist die Aufgabe, wenn die endgültige Diagnose den Payload-Vergleich beibehält, statt sich auf EventPayloads als Ganzes zu beziehen.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.