Dart JS Interop 函数重载以进行键入
Dart JS Interop Function overloading for typing
我已经定义了一个 D3 Dart JS Interop,我用它来设置 D3 对象的值并调用它们,效果很好。不幸的是,D3 对 setters 和 getters 使用相同的函数,并且取决于将它们分开的参数数量。
例如,Arc 对象可以像这样设置和获取 InnerRadius(在 JavaScript 中):
var arc = d3.arc().innerRadius(25);
//arc with innerRadius of 25
var radius = arc.innerRadius();
//radius is 25
我定义的 Dart 包装器如下所示:
@JS('d3')
library d3;
import 'dart:js';
import "package:js/js.dart";
@JS("arc")
class Arc {
external Arc innerRadius(num innerRadius);
external Arc();
}
我想像这样定义一个包装器:
@JS("arc")
class Arc {
external Arc innerRadius(num innerRadius);
external num innerRadius();
external Arc();
}
但是它抱怨名称已经被定义。我如何定义 dart 包装器以便我可以在输入值的同时设置和调用值?
D3 定义了这样一个弧:
function arcInnerRadius(d) {
return d.innerRadius;
}
function constant(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(+_);
}
return arc;
}
return innerRadius;
}
return arc;
}
因此 getter 和 setter 语法没有正确包装它。由于设置 innerRadius 设置了代码未调用的函数,而不是内部值。
有一个丑陋的解决方案,其中如果您放弃输入并将参数设为可选,它允许您同时执行这两项操作。所以我目前的解决方案是像这样定义包装器:
@JS('d3')
library d3;
import 'dart:js';
import "package:js/js.dart";
@JS("arc")
class Arc {
external Arc();
external innerRadius([num innerRadius]);
}
允许您这样称呼它:
Arc arc = new Arc()
..innerRadius(25);
num radius = arc.innerRadius();
这可行,但缺点是我们失去了一些输入值,因为我无法输入强制半径为数字。也就是说,这同样有效:
Point<num> radius = arc.innerRadius();
直到 运行 时间才会爆炸。
所以这与它正在映射的函数相匹配并且它可以工作,但我真正想要的是能够使用类型来实现它,从而定义一个具有相同名称的函数,它既可以 return同款。
如果我正确理解你的问题,你希望能够设置 innerRadius(value) 并获取 innerRadius。为此,我会执行以下操作...
external Arc set innerRadius(num value);
external num get innerRadius;
以上几乎完全符合您的要求,除了 getter 将以下列方式使用...
num radius = arc.innerRadius;
我们不再需要定义我们自己的 JavaScript 定义文件,因为 Dart 有一个工具可以从 TypeScript 文件中这样做。 JS Facade Generator。
official Dart Page about JS Interoperability.
上有更多关于使用它的信息
感谢 DefinitelyTyped project,几乎肯定有一个 TypeScript 文件可以让您执行此操作。如果没有,请改为编写其中一个,它将对 Dart 和 TypeScript 社区都有帮助。
我已经定义了一个 D3 Dart JS Interop,我用它来设置 D3 对象的值并调用它们,效果很好。不幸的是,D3 对 setters 和 getters 使用相同的函数,并且取决于将它们分开的参数数量。
例如,Arc 对象可以像这样设置和获取 InnerRadius(在 JavaScript 中):
var arc = d3.arc().innerRadius(25);
//arc with innerRadius of 25
var radius = arc.innerRadius();
//radius is 25
我定义的 Dart 包装器如下所示:
@JS('d3')
library d3;
import 'dart:js';
import "package:js/js.dart";
@JS("arc")
class Arc {
external Arc innerRadius(num innerRadius);
external Arc();
}
我想像这样定义一个包装器:
@JS("arc")
class Arc {
external Arc innerRadius(num innerRadius);
external num innerRadius();
external Arc();
}
但是它抱怨名称已经被定义。我如何定义 dart 包装器以便我可以在输入值的同时设置和调用值?
D3 定义了这样一个弧:
function arcInnerRadius(d) {
return d.innerRadius;
}
function constant(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(+_);
}
return arc;
}
return innerRadius;
}
return arc;
}
因此 getter 和 setter 语法没有正确包装它。由于设置 innerRadius 设置了代码未调用的函数,而不是内部值。
有一个丑陋的解决方案,其中如果您放弃输入并将参数设为可选,它允许您同时执行这两项操作。所以我目前的解决方案是像这样定义包装器:
@JS('d3')
library d3;
import 'dart:js';
import "package:js/js.dart";
@JS("arc")
class Arc {
external Arc();
external innerRadius([num innerRadius]);
}
允许您这样称呼它:
Arc arc = new Arc()
..innerRadius(25);
num radius = arc.innerRadius();
这可行,但缺点是我们失去了一些输入值,因为我无法输入强制半径为数字。也就是说,这同样有效:
Point<num> radius = arc.innerRadius();
直到 运行 时间才会爆炸。
所以这与它正在映射的函数相匹配并且它可以工作,但我真正想要的是能够使用类型来实现它,从而定义一个具有相同名称的函数,它既可以 return同款。
如果我正确理解你的问题,你希望能够设置 innerRadius(value) 并获取 innerRadius。为此,我会执行以下操作...
external Arc set innerRadius(num value);
external num get innerRadius;
以上几乎完全符合您的要求,除了 getter 将以下列方式使用...
num radius = arc.innerRadius;
我们不再需要定义我们自己的 JavaScript 定义文件,因为 Dart 有一个工具可以从 TypeScript 文件中这样做。 JS Facade Generator。 official Dart Page about JS Interoperability.
上有更多关于使用它的信息感谢 DefinitelyTyped project,几乎肯定有一个 TypeScript 文件可以让您执行此操作。如果没有,请改为编写其中一个,它将对 Dart 和 TypeScript 社区都有帮助。