javascript - typescript - 表示类型中的模块模式

标签 javascript typescript d3.js

我尝试将以下代码设为强类型,以便更容易维护。

但是对于菜单变量我收到以下错误:

[ts]
Type '(x: number, y: number) => void' is not assignable to type 'ContextMenu'.
  Property 'items' is missing in type '(x: number, y: number) => void'.



import * as d3 from "d3";
import "d3-selection-multi";

interface ContextMenu {
    (x: number, y: number) : void;
    items(items?: string[]): string[] | this;
    remove(): void;
}

export function contextMenu(): ContextMenu {
    var height,
        width, 
        margin = 0.1, // fraction of width
        items = [], 
        rescale: boolean = false, 
        style = {
            'rect': {
                'mouseout': {
                    "fill": 'rgb(244,244,244)', 
                    "stroke": 'white', 
                    "strokeWidth": '1px'
                }, 
                'mouseover': {
                    "fill": 'rgb(200,200,200)'
                }
            }, 
            'text': {
                'fill': 'steelblue', 
                'font-size': '13'
            }
        }; 

    var menu: ContextMenu = function (x:number, y:number) {
        menu.remove();
        scaleItems();

        // Draw the menu
        d3.selectAll('svg.chart')
            .append('g').attr('class', 'context-menu')
            .selectAll('tmp')
            .data(items).enter()
            .append('g').attr('class', 'menu-entry')
            .style('cursor', 'pointer')
            .on('mouseover', function() {
                d3.select(this).select('rect').styles((<any>style).rect.mouseover) })
            .on('mouseout', function() {
                d3.select(this).select('rect').styles((<any>style).rect.mouseout) });

        d3.selectAll('.menu-entry')
            .append('rect')
            .attr('x', x)
            .attr('y', (d, i) => y + (i * height))
            .attr('width', width)
            .attr('height', height)
            .styles((<any>style).rect.mouseout);

        d3.selectAll('.menu-entry')
            .append('text')
            .text((d: string) => d)
            .attr('x', x)
            .attr('y', (d, i) => y + (i * height))
            .attr('dy', height - margin / 2)
            .attr('dx', margin)
            .styles((<any>style).text);

        // Other interactions
        d3.select('body')
            .on('click', function() {
                d3.select('.context-menu').remove();
            });
    }

    menu.remove = function() {
        d3.selectAll(".context-menu").remove();
    };

    menu.items = function(_?) {
        return (!arguments.length) 
        ? items 
        :(items = _, rescale = true, menu);
    }

    // Automatically set width, height, and margin;
    function scaleItems() {
        if (!rescale) {
            return;
        }
        d3.selectAll('svg').selectAll('tmp')
            .data(items).enter()
            .append('text')
            .text(d => d)
            .styles(<any>style.text)
            .attr('x', -1000)
            .attr('y', -1000)
            .attr('class', 'tmp');

        var z = d3.selectAll('.tmp')
            .nodes()
            .map((x:any) => x.getBBox());

        width = d3.max(z.map(x => x.width));
        margin = margin * width;
        width =  width + 2 * margin;
        height = d3.max(z.map(x => x.height + margin / 2 ));

        // cleanup
        d3.selectAll('.tmp').remove();
        rescale = false;
    }
    return menu;
}

如何使代码编译但保持相同的代码风格惯用的 D3?

最佳答案

遗憾的是,在您的情况下没有惯用的方法来扩展功能。唯一的后备方案是将菜单功能转换为 any

var menu: ContextMenu = function (x:number, y:number) {
    // ....
} as any
<小时/>

TypeScript 还有另一个功能,称为“命名空间合并”,以适应扩展函数文字。

function menu () {}
namespace menu {
  export function remove() {}
}
menu.remove() // compiles

但是,命名空间只能出现在模块的顶层或嵌套在另一个命名空间中。您不能在函数闭包中声明它。因此,在这种情况下,您必须以任何方式回退到any

关于javascript - typescript - 表示类型中的模块模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44180919/

相关文章:

javascript - 专注于输入字段

reactjs - axios错误处理err.response对象

TypeScript:条件类型和使用 bool 参数来控制返回类型

javascript - 使用 dc.js 的日期堆积面积图

javascript - 谷歌API V3 : How to remove overlay using Custom Overlay's onRemove() method

javascript - D3.js 条形图动画不正确并在动画后留下伪像

javascript - 在 CMB Metabox 上添加选项卡

javascript - HTML/CSS/JS 画线

javascript - 使用 Javascript 将十六进制数转为字符

Angular 2 : How to display console response data?