Typescript 期望从 d3.nest().rollup() 中的辅助函数返回 undefined

Typescript expects undefined to be returned from helper function in d3.nest().rollup()

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

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() 到 return 未定义,这对我来说没有意义,并且这段代码在纯 javascript 中运行良好。只嵌套数据而不使用 rollup() 也可以。

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

谢谢, 托马斯

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

这个错误,以及您在 d3 类型中发现的几乎所有其他不一致,都可以通过简单地将冲突元素转换为 any 类型来忽略:

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 来提供帮助,如果没有则提交新问题。

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

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

Nest<Datum, RollupType>接口中第一个泛型Datum指的是数据array元素的数据类型进入 Nest 生成器的以下方法:

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

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

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

第二个泛型约束 Nest 生成器,RollupType 仅在打算 configure/use rollup(...) 访问器时才相关,就像您的情况一样。它控制汇总功能的 return 类型。

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

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

}

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

如果您在简单地调用 d3.nest() 时不使用泛型,默认值将意味着您 return 被 Nest<{}, undefined> 调用了。这迫使您遇到的错误有点 微调 以确保嵌套底层的数据类型对应于方法和访问函数中的 argument/return 类型。

也就是说,有一个较长的评论与 map(...)object(...) 和 [=19] 的 return 类型相关=] 定义文件中的方法。它揭示了嵌套过程的复杂性,i.p。如果使用卷起。你可以找到它 here.

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

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

希望这有助于解释。