ngrx Nutzlast in Reducer-Aktion wird nicht kompiliert

8

Ich versuche, meine eckige App 2 zu eckigen 4 und ngrx 4 zu migrieren.

Ich beschäftige mich mit einem seltsamen Typoskript-Kompilierungsproblem, das ich vor diesem Update nicht hatte. Ich arbeite in einer Offline-Umgebung, daher kann ich den genauen Code hier nicht teilen.

Ich habe online nach dem Problem gesucht, das nächste, was ich finden konnte, war diese Frage: Frage zu Payload-Typen Der Code in dieser Frage ähnelt in gewisser Weise dem, was ich versuche zu tun, aber der Unterschied besteht darin, dass ich das ActionTypes-Objekt aus der Aktion entfernt habe (was die vorgeschlagene Antwort für diese Frage ist), aber es hat meinen Kompilierungsfehler nicht gelöst.

Ich kann hier nicht den genauen Code angeben, aber ich basiere meinen Code vollständig auf dem ngrx-Beispiel ngrx offizielles Beispiel auf github

Schauen wir uns zum Beispiel Buchreduktion und Buchaktionen an Aktionen buchen Buchreduzierer

Mein Code ist im Grunde der gleiche, und der Fehler tritt bei jedem Reducer-Fall auf (im Switch-Fall), wenn ich versuche, die Payload aus der Aktion zu entfernen. Es sagt mir etwas wie:

%Vor%

(In meinem Code habe ich anstelle von Buch verschiedene Klassen, aber es ist ziemlich die gleiche Idee)

Im Moment löse ich die Fehler, indem ich den Aktionstyp von A | B | B Dies ist der spezifische Aktionstyp, der dem Fall im Switch entspricht (mit dem Schlüsselwort as typscript). Diese Lösung fühlt sich schlecht und hacky an, ich würde gerne wissen, ob es eine bessere gibt.

Die Versionen verwenden: typescript: 2.4.1 (Ich vermute, dass es mit ngrx-Beispielen verbunden sein könnte, die nicht dieselbe aktualisierte Typoskript-Version wie ich verwenden) ngrx @ speichern: 4.0.3 ngrx @ Kern: 1.2.0 eckig: (Spätestens ab 17.9.17 gibt es viele Pakete innerhalb eckig, und ich denke nicht, dass es accutal wichtig ist, welchen Winkel ich für diesen Fehler benutze, aber ich sage das nur, um auf der sicheren Seite zu sein) Typoskript: (2.4.1) (Ich habe das offizielle Migrationsdokument von ngrx gelesen, in dem es darum ging, Typoskript zu aktualisieren, und ich tat es)

UPDATE: Da ich eine Antwort bekommen habe, die für mein Problem nicht relevant ist und auch gefragt wurde, hier ist der Teil meines Codes, der fehlschlägt (ich kann den genauen Beitrag nicht posten, aber ich kopiere die relevanten Teile):

mission-reducer.ts:

%Vor%

mission-action.ts:

%Vor%

Zum Schluss verstehe ich, warum es Sinn macht, wenn Typoskript den Action-Payload-Typ string | Mission | ... Aber in dem ngrx-Beispiel, auf dem ich das aufbaute, scheint es, dass Typoskript dort den spezifischen Typ in dem Fall erkennt, aber für mich funktioniert das nicht aus einem Grund, den ich nicht verstehe, könnte etwas mit mir zu tun mit Typoskript 2.4 .1? nicht sicher, brauche Hilfe mit diesem

    
Ziv Glazer 17.09.2017, 12:20
quelle

2 Antworten

6

Das Problem besteht darin, dass das Verhalten des Codes und seiner Typanmerkungen sich gegenseitig überschneiden.

Eigentlich würde ich sagen, dass der Code übermäßig kommentiert ist.

Union-Typen und die Fallanalyse, die sie ermöglichen, funktionieren über Typ-Inferenz- und Kontrollfluss-basierte Typanalyse, zwei der leistungsfähigsten Funktionen von TypeScript. Der Prozess, durch den der Typchecker Möglichkeiten aus der Vereinigung eliminiert, wird engering genannt.

Wie der Code andeutet, kann ein Union-Typ in seine Bestandteile zerlegt werden, indem ein Werttest für eine als Diskriminante bekannte Eigenschaft durchgeführt wird.

Eine Diskriminante ist eine Eigenschaft, deren Typ eine endliche Menge möglicher Werte hat, wobei jeder Wert im Allgemeinen einem Fall der Vereinigung entspricht.

string ist keine gültige Diskriminante, aber "hello world" ist. (Als Überbegriff aller möglichen Strings kollabiert eine Vereinigung von Stringtypen einschließlich string zu nur string )

Wenn wir in TypeScript eine Eigenschaft const oder eine readonly definieren, leitet der Compiler den Typ als Typ des initialisierenden Literals ab.

Überlegen Sie:

%Vor%

Hier ist der Typ von kind nicht string , sondern "first" .

Ähnliches gilt für

%Vor%

Der Typ der Eigenschaft kind ist nicht string , sondern "first" .

In unserem Code ist die Diskriminante eine Eigenschaft namens type , die von jedem Bestandteil der Union definiert wird.

Aber während Sie für jedes Element eindeutige Werte angegeben haben, haben Sie sie mit Typanmerkungen überbezeichnet, die eine Einengung verhindern.

Was Sie haben:

%Vor%

Was Sie wollen:

%Vor%

Ein funktionierendes switch

%Vor%

Warum das wichtig ist:

Ein String-Literaltyp ist ein allgemeiner und idiomatischer Weg, der die Möglichkeiten einer Vereinigung unterscheidet, aber indem wir die implementierenden Eigenschaften vom Typ string deklarieren, ein Typ, der ein Super-Typ aller String-Literaltypen ist, haben wir den Typ gesperrt Schlussfolgerung und dadurch eine Verengung verhindert. Beachten Sie, dass string kein Typ ist, von dem keine Einschränkung möglich ist.

Im Allgemeinen ist es am besten, TypeScript-Typ-Inferenz zu nutzen, wenn ein Wert einen Initialisierer hat. Sie werden nicht nur das erwartete Szenario aktivieren, sondern Sie werden auch von der Anzahl der Fehler beeindruckt sein, die der Typinterferencer einfangen wird. Wir sollten dem Compiler nicht mehr sagen, als er wissen muss, es sei denn, wir wollen absichtlich einen Typ, der allgemeiner ist als der, auf den er sich bezieht. Mit --noImplicitAny wird es uns immer mitteilen, wenn wir zusätzliche Informationen in Form von Typ-Annotationen angeben müssen.

Anmerkungen:

Sie können die Typen technisch festlegen und das Einschränkungsverhalten beibehalten, indem Sie den Literalwert als Typ der Eigenschaft const oder readonly angeben. Dies erhöht jedoch die Wartungskosten und ist ziemlich redundant.

Zum Beispiel gilt Folgendes:

%Vor%

aber du wiederholst dich nur unnötigerweise.

In ihrer Antwort bietet ilyabasiuk einige großartige Referenzlinks zur Verwendung von literalen Typen speziell mit ngrx und wie es sich in den letzten Iterationen der TypeScript-Sprache entwickelt hat.

Um zu verstehen, warum literale Typen in unveränderlichen Positionen hergeleitet werden, sollten Sie beachten, dass dies eine leistungsfähige statische Analyse und somit eine bessere Fehlererkennung ermöglicht.

Überlegen Sie:

%Vor%     
Aluan Haddad 01.11.2017, 20:00
quelle
2

Hier ist eine wirklich gute Beschreibung der Migration, die Sie versuchen Ссылка zu tun

Sie müssen die nächsten Änderungen vornehmen:

  • Löschtypdefinition für Aktion const string;
  • Löschtypdefinition für Typeigenschaft;
  • add / * tslint: disable: typedef * / am Anfang der Datei, wenn Ihr tslint so konfiguriert wurde, dass keine Definition eines verpassten Typs erlaubt wird (yep, es sieht so aus nicht sehr gut, aber wenn ich zwischen starken Regeln für den Typ wählen muss definition in aktionsdateien und unterstützungsarten in reduzierern werde ich wählen Sie auf jeden Fall den zweiten);

Sie erhalten also etwas wie:

%Vor%

Aluan Haddad hat eine gute Erklärung dafür gegeben, warum es so im Post oben funktioniert.

    
ilyabasiuk 02.11.2017 08:14
quelle