【问题标题】:Typescript expects undefined to be returned from helper function in d3.nest().rollup()Typescript 期望从 d3.nest().rollup() 中的辅助函数返回未定义
【发布时间】:2017-05-14 05:19:34
【问题描述】:

我目前正在 D3 (v4.4.0) 和 Typsecript 中构建可视化,并从 @types/d3 安装了类型。对于可视化,我需要嵌套我的数据。这是我试图用这个 sn-p 做的,它应该计算每个键的条目数:

d3.nest()
  .key(function(d: any) {return d.key;})
  .rollup(function(leaves: any){
    return d3.sum(leaves, function (d) {
      return 1;
    })
  })
  .entries(this.data);

对于汇总方法中的辅助函数,我得到一个类型错误:

severity: 'Error'
message: 'Argument of type '(leaves: any) => number' is not assignable to parameter of type '(values: {}[]) => undefined'.
Type 'number' is not assignable to type 'undefined'.'
at: '46,15'
source: 'ts'

看来 tsc 期望 rollup() 返回 undefined,这对我来说没有意义,而且这段代码在纯 javascript 中运行良好。仅嵌套数据而不使用 rollup() 也可以。

有人知道这里出了什么问题吗?

谢谢, 托马斯

【问题讨论】:

    标签: d3.js typescript typescript-typings


    【解决方案1】:

    rollup() 方法的签名声明似乎有问题。

    只需将冲突元素转换为 any 类型,即可忽略此错误以及您在 d3 类型中发现的几乎所有其他不一致:

    d3.nest()
      .key(function(d: any) {return d.key;})
      .rollup(function(leaves: any){
        return d3.sum(leaves, function (d) {
          return 1;
        }) as any
      })
      .entries(this.data);
    

    D3 API 非常庞大,因此您可能会在不太受欢迎的功能中发现更多类似的错误。您可以通过搜索是否有与您发现的错误相关的 already an open issue 来提供帮助,如果没有,请提交新问题。

    【讨论】:

    • 谢谢。添加“任意”有效。我认为这可能是类型定义的问题。我将打开一个问题。
    【解决方案2】:

    在 D3 v4 中,d3.nest() 工厂有几个签名。它们之间的唯一区别是您可以对两个控制数据类型的泛型进行多少控制,这些泛型限制了返回的Nest<Datum, RollupType> 生成器。

    由于 d3-collection 的 JSDoc cmets 的完成仍然是一个跟踪待办事项,我将在此期间提供一个简短的解释。

    在Nest<Datum, RollupType> 接口中,第一个泛型Datum 指代传递给Nest 生成器的以下方法的数据array 中的元素 的数据类型:

    • map(...)
    • object(...)
    • entries(...)

    出于同样的原因,它是 key 访问器函数的参数的数据类型,并且在您的情况下,array 的元素的数据类型作为传递给汇总函数论据。

    因此,在调用 d3.nest() 工厂时明确设置 Datum 始终是谨慎的做法(见下文)。

    第二个通用约束 Nest 生成器 RollupType 仅在打算配置/使用 rollup(...) 访问器时才相关,就像您的情况一样。它控制汇总函数的返回类型。

    因此,话虽如此,由于您需要汇总功能,因此您应该使用以下内容,根据要嵌套的源数据类型量身定制:

    interface YourDatum {
      key: string;
      // any proprties related to the value of this element
    }
    
    let data: YourDatum[];
    
    data = [/* set your data */]
    
    d3.nest<YourDatum, number>()
      .key(function (d) { return d.key; })
      .rollup(function (leaves) {
        return d3.sum(leaves, function (d) {
          return 1;
        })
      })
      .entries(data);
    

    }

    请注意,传入key 和rollup 的访问器函数受接口定义和泛型指定类型的约束。

    如果您在简单地调用d3.nest() 时不使用泛型,默认值将意味着您将返回Nest&lt;{}, undefined&gt;。这会迫使您稍微轻推时遇到错误,以确保嵌套底层的数据类型与方法和访问器函数中的参数/返回类型相对应。

    话虽如此,定义文件中有一个较长的注释与map(...)、object(...) 和entries(...) 方法的return 类型相关。它揭示了嵌套过程的复杂性,i.p.如果使用汇总。你可以找到它here。

    在工厂中使用泛型,现在在 D3 v4 定义中相当广泛。

    作为最后的评论,我还在 DefinitiveTyped 上跟踪一个问题,以验证 strictNullChecks 的 d3-collection。当我有一个安静的时刻时,将与 JSDoc cmets 一起这样做......

    希望这有助于解释。

    【讨论】:

    • 感谢您的大力支持。按照您的解释解决了问题。
    猜你喜欢
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    • 2016-11-25
    • 2017-12-04
    • 2018-12-13
    相关资源
    最近更新 更多