Der Versuch, die Grenzen von 'T zu verstehen, erweitert infer U'

8

Ich habe das so verstanden wie:

type GenericExample<T> = T extends (infer U) ? U : 'bar';

entspricht:

type GenericExample<T> = T extends T ? T : 'bar';

Aber wenn die Dinge aufwändiger werden, beschwert sich TypeScript:

type Types = 'text' | 'date' | 'articles' | 'params';

type MyExperiment<Type extends Types> =  { t : Type };

type MyExperimentsUnion = Types extends (infer U) ? MyExperiment<U> : never;
// Type 'U' does not satisfy the constraint 'Types'.
// Type 'U' is not assignable to type '"params"'.

Ich möchte also fragen, warum dies falsch ist: In diesem speziellen Fall sollte eine Verteilung über die Gewerkschaft stattfinden, also sollte der abgeleitete UTyp textdann dateund so weiter sein. Was bedeutet es also T extends (infer U)wirklich und wann wäre es angebracht, es zu verwenden?

Andrea Simone Costa
quelle

Antworten:

0

Ich glaube nicht, dass es so verwendet werden sollte, wie Sie es verwenden - im Grunde infersollte es verwendet werden, um den Typ "abzuleiten" (oder vielleicht eine bessere Benennung aufzulösen?), Am häufigsten von einem Generikum.

So wie Sie es verwenden, erstellen Sie einen Typ, der keinen "dynamischen" Teil hat (im Grunde ist er nicht generisch), was bedeutet, dass er immer derselbe ist, und daher macht es keinen Sinn, aus etwas zu schließen, das immer der gleiche ist . Weil Sie zum Zeitpunkt der Kompilierung bereits wissen, dass dies Typesnur erweitert wird Types & '...anything else', und da Sie diesen anderen Teil in Ihrem MyExperimentsUnionTyp nicht definieren können , inferhat er keinen großen Nutzen.

Anwendungsbeispiel

interface Action<T> {
    payload: T
}

type ExtractGeneric<T> = T extends Action<infer X> ? X : never

function getPayload<T extends Action<any>>(action: T): ExtractGeneric<T> {
    return action.payload;
}

const myAction = { payload: 'Test' };
const myPayloadWithResolvedType = getPayload(myAction);

Im obigen Beispiel myPayloadWithResolvedTypehätte der stringTyp aufgelöst, denn wenn Sie ihn nicht verwenden würden infer, müssten Sie diesen Rückgabetyp als zweiten Parameter übergeben, wahrscheinlich wie folgt:

function getPayloadNonExtract<T extends Action<U>, U>(action: T): U {
    return action.payload;
}

Hier ist der Link zum Spielplatz.

Prost.

zhuber
quelle
1
Hallo Mann, danke für deine Antwort! Ich muss sagen, dass ich den allgemeinen Zweck des inferSchlüsselworts kenne, aber ich habe diese seltsame Frage gestellt, weil ich festgestellt habe, dass sie T extends (infer U)in einem bedingten Typ gültig ist. Ich war darüber überrascht und begann zu untersuchen.
Andrea Simone Costa
1
Ich glaube, ich verstehe Ihre Frage, bin mir aber nicht sicher, wie Sie das Typoskript lösen möchten U. Was soll das MyExperiment<U>sein? Ich meine, Umuss "Unterklasse" von sein Types, aber Typoskript kann nicht genau bestimmen, was ist, Uda Sie keinen Typ übergeben (es ist kein generischer Typ), und ich verstehe nicht, warum es standardmäßig sein sollte Types. Ich denke, das ist einer der Gründe, warum Sie den Fehler erhalten, obwohl ich der Meinung bin, dass er aussagekräftiger sein könnte, aber es scheint, dass Entwickler der Meinung sind, dass dies infernicht für die Verwendung auf diese Weise gedacht ist.
zhuber
0

Es ist wahrscheinlich nicht mehr als zwei Cent wert, aber:

type Types = 'text' | 'date' | 'articles' | 'params';
type MyExperiment<Type extends Types> =  { t : Type };

type MyExperimentsGenericUnion<T extends Types> = T extends (infer U) ? MyExperiment<U> : never;
// same error

type MyExperimentsUnionConstraint = any extends MyExperiment<infer U> ? MyExperiment<U> : never;
// no error

Ich kann mir ein paar Gründe vorstellen, warum das MyExperimentsUnionConstraintfunktioniert, MyExperimentsUnionaber nicht, aber ich habe nicht die vertieften Sprachkenntnisse, um sie so auszudrücken, dass es Sinn macht.

Um eine Erklärung am Beispiel zu geben:

  • in MyExperimentsUnion, from Types extends U, Ukönnte als abgeleitet werden Types | 'bla'und MyExperiment<Type | 'bla'>funktioniert dann nicht.
  • in MyExperimentsUnionConstraint, Ukann nur als etwas zu entnehmen, dass mit WerkenMyExperiment
Artcorpse
quelle