2016-08-18 2 views
1

Ich habe ein D3 Dart JS Interop definiert, das ich verwende, um Werte auf D3-Objekten zu setzen und sie aufzurufen, was gut funktioniert. Leider verwendet D3 dieselbe Funktion sowohl für Setter als auch für Getter und hängt von der Anzahl der Argumente ab, um sie voneinander zu unterscheiden.Dart JS Interop Funktion Überladen für die Eingabe

Zum Beispiel hat das Arc Objekt die Möglichkeit, eine InnerRadius wie folgt aus (in JavaScript) zu setzen und zu erhalten:

var arc = d3.arc().innerRadius(25); 
//arc with innerRadius of 25 
var radius = arc.innerRadius(); 
//radius is 25 

Der Dart-Wrapper I definiert haben wie folgt aussieht:

@JS('d3') 
library d3; 

import 'dart:js'; 
import "package:js/js.dart"; 

@JS("arc") 
class Arc { 
    external Arc innerRadius(num innerRadius); 
    external Arc(); 
} 

Und ich möchte einen Wrapper wie folgt definieren:

@JS("arc") 
class Arc { 
    external Arc innerRadius(num innerRadius); 
    external num innerRadius(); 
    external Arc(); 
} 

Aber es beschwert sich über der Name schon sein definiert. Wie definiere ich den Dart Wrapper, damit ich den Wert sowohl setzen als auch abrufen kann, während ich ihn auch eintippe?

D3 definiert einen Bogen wie folgt aus:

function arcInnerRadius(d) { 
    return d.innerRadius; 
} 

function constant$1(x) { 
    return function constant() { 
     return x; 
    } 
} 

function arc() { 
    var innerRadius = arcInnerRadius; 

    function arc() { 
     var r0 = +innerRadius.apply(this, arguments); 
     //calculate and return path 
    } 

    arc.innerRadius = function(_) { 
     if(arguments.length) { 
      if(_ === "function") { 
       innerRadius = _; 
      } else { 
       innerRadius = constant$1(+_); 
      } 
      return arc; 
     } 
     return innerRadius; 
    } 

    return arc; 
} 

So ist die Getter und Setter-Syntax nicht korrekt umbrochen. Als Einstellung setzt innerRadius die Funktion, die nicht vom Code aufgerufen wird, nicht den internen Wert, der lautet.

Es gibt eine hässliche Lösung, bei der man, wenn man die Eingabe weglässt und den Parameter optional macht, beides erlaubt. Also meine aktuelle Lösung ist die Verpackung so zu definieren:

@JS('d3') 
library d3; 

import 'dart:js'; 
import "package:js/js.dart"; 


@JS("arc") 
class Arc { 
    external Arc(); 
    external innerRadius([num innerRadius]); 
} 

Welche Sie es so nennen kann:

Arc arc = new Arc() 
    ..innerRadius(25); 
num radius = arc.innerRadius(); 

Dies funktioniert, hat aber den Nachteil, dass wir einen Teil des Wertes verlieren von Tippen, dass ich nicht tippen kann, erzwinge den Radius als Zahl. Das heißt, das ist gleichwertig:

Point<num> radius = arc.innerRadius(); 

Und es wird nicht bis zur Laufzeit explodieren.

Also das entspricht der Funktion, die es zugeordnet ist und es funktioniert, aber was ich wirklich bin, ist die Fähigkeit, es mit Typen zu tun und so eine Funktion mit dem gleichen Namen zu definieren, die beide den gleichen Typ zurückgeben können.

Antwort

0

Wir Sie müssen nicht mehr unsere eigenen JavaScript-Definitionsdateien definieren, da Dart dafür ein Tool aus TypeScript-Dateien zur Verfügung hat. Die JS Facade Generator. Es gibt weitere Informationen zur Verwendung dieses auf der official Dart Page about JS Interoperability.

Dank der DefinitelyTyped project gibt es mit ziemlicher Sicherheit eine TypeScript-Datei, mit der Sie dies tun können. Ist dies nicht der Fall, schreibe stattdessen eine davon, damit wird sowohl den Dart- als auch den TypeScript-Communities geholfen.

1

Wenn ich deine Frage richtig verstanden habe, möchtest du innerRadius (Wert) setzen und innerRadius bekommen können. Denn das würde ich folgendes tun ...

external Arc set innerRadius(num value); 
external num get innerRadius; 

Die oben fast genau tun würde, was Sie fordern, mit Ausnahme der Getter würde in der folgenden Weise verwendet werden ...

num radius = arc.innerRadius; 
+0

Ich hatte dies versucht, aber es funktioniert nicht wegen der Art und Weise D3-Implementierung. Ich habe die Frage mit warum dies nicht funktioniert aktualisiert. Danke für den Vorschlag. :) –