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 Generatorofficial Dart Page about JS Interoperability.

上有更多关于使用它的信息

感谢 DefinitelyTyped project,几乎肯定有一个 TypeScript 文件可以让您执行此操作。如果没有,请改为编写其中一个,它将对 Dart 和 TypeScript 社区都有帮助。