microsoft / microsoft/TypeScript

Reverse mapped types don't use their constraint types when no candidates are present unlike the regular type parameters

Offen
#56,241 1 Kommentar 2 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

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

Beschreibung

🔎 Search Terms

reverse mapped constraint inference candidates

🕗 Version & Regression Information
  • This is the behavior in every version I tried
⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.3.0-dev.20231028#code/JYOwLgpgTgZghgYwgAgApynAthSVgBeEAJgPIBGAVhAmMgN4BQyyYAngA4QBcyAzmHwgA5gG5myDhmx8A-LwBKNAPZRiAHgFDhAGmQBXEAGsQygO4gAfOIC+jRsRoAbDChiHawZSH659HdQkAFQBhb0gADzAdYIBxfQxiPmQIKIgQJOQlBFUNLVBdNGkcPEISCmpaAG0AIilMLD4agF1kAB8DDIgYUBJLGMsACgB9XiYWdi4+MYkWHPBUsF5Q8MXxFht15GEEtWmGWeQqgGlkUGQjCDZlGGQg+MS+Zt5B+cilu7CFqL16mWWHnsTs0AJTIAC8lmQADdlMBiFtNowbCCAbskuJGPMBMgoBA+PonHRwb4wP5BuNWJx8TMWHNVlFaXT6YYPgBGAAMHJizJsPOQfIkO0eTLmAAsaEYAGLKZQvYZ6ejIGCygVjZWy3j5EQCsGQjXKCHgkk1FXKGr8lhwJxmOBsPhBKD6HjIEZ6qGCZ38wUozF4glE8QAeiDyAAerJ7IwgA

💻 Code
interface ParameterizedObject {
  type: string;
  params?: Record<string, unknown>;
}

declare function setup<
  TContext,
  TGuards extends Record<string, ParameterizedObject["params"] | undefined>,
>(_: {
  types: {
    context: TContext;
  };
  guards: {
    [K in keyof TGuards]: (context: TContext, params: TGuards[K]) => void;
  };
}): TGuards;

const result = setup({
  types: {
    context: {
      count: 100,
    },
  },
  guards: {
    checkFoo: (_, { foo }: { foo: string }) => foo === "foo",
    alwaysTrue: (_) => true,
  },
});

result;
// ^?
🙁 Actual behavior
Type '(_: { count: number; }, { foo }: { foo: string; }) => boolean' is not assignable to type '(context: { count: number; }, params: Record<string, unknown> | undefined) => void'.
  Types of parameters '__1' and 'params' are incompatible.
    Type 'Record<string, unknown> | undefined' is not assignable to type '{ foo: string; }'.
      Type 'undefined' is not assignable to type '{ foo: string; }'.(2322)
🙂 Expected behavior

I'd expect the inference to succeed here

Additional information about the issue

TGuards is inferred as { checkFoo: { foo: string; }; alwaysTrue: unknown; } and thus rejected by the constraint check in getInferredType. alwaysTrue is inferred as unknown because inferReverseMappedType has such a return:

return getTypeFromInference(inference) || unknownType

And getTypeFromInference doesn't attempt to read the type parameter's constraint at all. It simply handles .candidates and .contraCandidates and that's it.

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

Beginne mit der Playground-Reproduktion und verfolge die im Bericht genannten Pfade der Typprüfung: getInferredType, inferReverseMappedType und getTypeFromInference. Untersuche, wie Constraint-Typen behandelt werden, wenn die Reverse-Mapped-Inferenz keine Kandidaten hat; die Aufgabe ist abgeschlossen, wenn der bereitgestellte Setup-Aufruf erfolgreich und ohne den gezeigten Constraint-Fehler inferiert wird.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

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