'string | 类型的参数 null' 不可分配给类型为 'ValueFn<SVGPathElement, Datum[], string | 的参数 数量 | 布尔值 | 空>'

IT技术 javascript reactjs typescript d3.js
2021-05-02 14:53:10

我是 d3 的新手,并尝试使用 d3、TypeScript 和 react 来实现最小折线图。但它总是会导致 TypeScript 错误。在我的图表被错误消息替换之前,我什至会看到一秒钟的图表。

我尽可能将 d3 部分与 react 代码分开。有一种react成分呈现一个dividcomponentDidUpdateid被传递给draw函数在一个单独的文件,我所有的D3代码(代码如下所示)。我试图为所有可以输入的东西提供一个类型。

import * as d3 from 'd3'

type Props = { id: string }
type Datum = {x: number, y: number}
type Data = Array<Datum>

const draw = (props: Props) => {
    const data = [
        { x: 1, y: 5 },
        { x: 20, y: 20 },
        { x: 40, y: 10 },
        { x: 60, y: 40 },
        { x: 80, y: 5 },
        { x: 100, y: 60 },
    ]
    const container = d3.select<HTMLElement, any>('#' + props.id)
    container.selectAll<HTMLElement, any>('*').remove()
    const svg = container.append<SVGElement>('svg')
    const lineGenerator = d3.line<Datum>()
        .x((d: Datum) => d.x)
        .y((d: Datum) => d.y)

    svg.append<SVGPathElement>('path')
        .datum<Data>(data)
        .attr('fill', 'none')
        .attr('stroke', 'steelblue')
        .attr('stroke-width', 1.5)
        .attr('d', lineGenerator(data))
}

export default draw

就像我说的,图表是可见的,但很快就会消失,而是我得到:

... ... 中的
TypeScript 错误:
'string | 类型的参数 | null' 不可分配给类型为 'ValueFn<SVGPathElement, Datum[], string | 的参数 数量 | 布尔值 | 空>'。
      类型 'null' 不能分配给类型 'ValueFn<SVGPathElement, Datum[], string | 数量 | 布尔值 | 空>'。TS2345

    26 |         .attr('stroke', 'steelblue')
    27 |         .attr('stroke-width', 1.5)
  > 28 |         .attr('d', lineGenerator(data))
       |                    ^
    29 | }
    30 | 
    31 | export default draw

任何想法argument of type string | null来自哪里以及如何解决该错误?

编辑:由于结果证明与问题无关,为了清楚起见,我删除了react代码。

1个回答

这个问题是 TypeScript 等价于各种类型的 JavaScript 问题,这些问题时不时出现,开发人员将通过引用传递函数与原位调用所述函数混淆,从而仅传递其返回值。

您实际上是通过执行 来调用(即执行)行生成器lineGenerator(data)正如您从 API文档类型定义中看到的,这将返回字符串或空值:

export interface Line<Datum> {
  (data: Datum[]): string | null;
  //...
}

但是,这.attr()方法的签名不匹配,在这种情况下,它希望将函数作为第二个参数传递。

export interface Selection<GElement extends BaseType, Datum, PElement extends BaseType, PDatum> {
  //...
  attr(name: string, value: ValueFn<GElement, Datum, string | number | boolean | null>): this;
  //...
}

解决方案是将生成器传递给.attr()而不执行它:

.attr('d', lineGenerator)

然后生成器将.attr()通过传递绑定到选择的数据的内部工作来执行反过来,这将返回路径d属性的路径定义字符串