2017-04-17 2 views
1

Ich habe eine Pseudo Union Typ von einem js zurückgegeben.Wie extrahiere ich den richtigen Typ aus meinem Pseudo-Union-Typ

Hier ist mein scalajs:

 

    @js.native 
    trait ErrorResponse extends js.Object { 
     val error: String = js.native 
     val errorDescription: String = js.native 
    } 

    @js.native 
    trait TokenResponse extends js.Object{ 
     val accessToken: String = js.native 
     val expriseOn: js.Date = js.native 
     val tokenType: String = js.native 
     val userId: String = js.native 
     val identityProvider: String = js.native 
    } 

und meine scalajs

 

    @js.native 
    @JSImport("mymodule", "JSClassInModule") 
    class JSClassInModule extends js.Object { 
     // ... 
     def scalajsfunc(): ErrorResponse | TokenResponse = js.native 
     // .. 
    } 

Wenn ich scalajsfunc nennen, wie einkochen ich idiomatisch den zurückgegebenen Wert zu einem der beiden in meinem pseudo- angegebenen Klassen Gewerkschaftsklasse?

Antwort

2

Verwenden Mustervergleich:

val jsClassInModule: JSClassInModule = ??? 
(jsClassInModule.scalajsfunc(): Any) match { 
    case response: ErrorResponse => ... 
    case response: TokenResponse => ... 
} 

Die Zuschreibung : Any ist notwendig, um die Tatsache zu arbeiten, dass der Scala Typ-Checker nicht über die spezifische Semantik von | nicht kennt, und gibt falsche Fehlermeldungen, wenn Sie direkt versuchen, passen auf eine |.

Edit: Wenn die einzelnen Typen sind JS traits, also Eigenschaften, die js.Any verlängern, wird die oben nicht funktionieren, da es im Allgemeinen nicht möglich ist, isInstanceOf Tests mit JS Züge auszuführen (was, was Muster Matching tut, und ist meist nicht verwandt mit |). Stattdessen müssen Sie den Instanztest, der Sinn ergibt, codieren und dann den Cast ausführen. Zum Beispiel gehen wir einen ErrorResponse von einem TokenResponse durch Testen auf das Vorliegen eines errorCode Eigenschaft kann sagen, könnten wir tun:

val jsClassInModule: JSClassInModule = ??? 
(jsClassInModule.scalajsfunc(): Any) match { 
    case response if js.Object.hasOwnProperty(response, "errorCode") => 
    val errorResponse = response.asInstanceOf[ErrorResponse] 
    ... 
    case response => 
    val tokenResponse = response.asInstanceOf[TokenResponse] 
    ... 
} 

So ist die hässliche Natur der JavaScript ist.

+0

Das schien nicht zu funktionieren. Jede Case-Klausel sagt: "wird nicht unterstützt, weil es eine rohe JS-Eigenschaft ist". Ich bin mir nicht sicher, wie es das sowieso bestimmen würde, da der einzige Unterschied in den Objekten einige Attribute sind, die definiert werden können oder auch nicht ... beide Seiten des | sind js.Objects. – user1763729

+0

Oh, das ist eine andere Sache, die meistens nichts mit '|' zu tun hat. Es gibt tatsächlich nichts, was der Scala.js-Compiler tun könnte, um zu testen, ob ein Objekt eine Instanz eines JS-Merkmals ist. In diesem Fall müssen Sie den Test selbst codieren und dann umwandeln. Siehe meine aktualisierte Antwort. – sjrd

+0

Das scheint es zu tun. Ich musste den if-Test an response.merge [js.Object] .hasProperty ("error") anpassen – user1763729

Verwandte Themen