2017-05-25 3 views
0

Ich habe den folgenden Code, den ich versuche, stark typisiert, so dass es leichter zu pflegen ist.Typoskript - Modulmuster in Typen

jedoch für das Menü Variable ich die folgende Fehlermeldung erhalten:

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

Howe kann ich den Code Kompilierung machen aber den gleichen Code Stil idiomatische D3 halten?

Antwort

1

Leider gibt es keine idiomatische Möglichkeit, die Funktion in Ihrem Fall zu erweitern. Der einzige Fallback besteht darin, die Menüfunktion auf any zu setzen.

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

Maschinenschrift hat eine andere Funktionalität calls "Namensraum Verschmelzen" Funktionsliteral aufzunehmen erstreckt.

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

jedoch namespace kann erscheint nur auf oberster Ebene eines Moduls oder in einem anderen Namensraum verschachtelt. Sie können es nicht in einem Funktionsabschluss deklarieren. In diesem Fall müssen Sie auf any zurückgreifen.

Verwandte Themen