【问题标题】:Dart JS Interop Function overloading for typing用于打字的 Dart JS 互操作函数重载
【发布时间】:2016-12-24 21:53:38
【问题描述】:

我已经定义了一个 D3 Dart JS 互操作,我用它来设置 D3 对象的值并调用它们,它运行良好。不幸的是,D3 对 setter 和 getter 使用相同的函数,并且取决于参数的数量来将它们分开。

例如,Arc 对象可以像这样(在 JavaScript 中)设置和获取 InnerRadius:

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 定义了这样的 Arc:

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;
}

因此,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();

它直到运行时才会爆炸。

所以这与它正在映射的函数匹配并且它可以工作,但我真正想要的是能够使用类型来完成它,从而定义一个可以返回相同类型的同名函数。

【问题讨论】:

    标签: d3.js dart dart-js-interop


    【解决方案1】:

    如果我正确理解您的问题,您希望能够设置 innerRadius(value) 并获取 innerRadius。为此,我将执行以下操作...

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

    上面的内容几乎完全符合您的要求,除了 getter 将以下列方式使用...

    num radius = arc.innerRadius;
    

    【讨论】:

    • 我试过这个,但由于 D3 的实现方式,它不起作用。我已经更新了为什么这不起作用的问题。 (还是)感谢你的建议。 :)
    【解决方案2】:

    我们不再需要定义自己的 JavaScript 定义文件,因为 Dart 有一个工具可以从 TypeScript 文件中执行此操作。 JS Facade Generator。 在official Dart Page about JS Interoperability 上有更多关于使用它的信息。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-21
      • 2019-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多