首页 > 解决方案 > 如何格式化 Y 轴以仅显示自然数?

问题描述

我在 Y 轴格式上中继任务以仅显示自然数时遇到问题。在项目中,我使用 React awith Typescript 和 Nivo Rocks 库来创建图表(https://nivo.rocks/)。为了这个问题,我创建了沙箱:

https://codesandbox.io/s/scuqn?file=/src/App.tsx

我找到了设置格式的解决方案:

  axisLeft={{
    format: e => Math.floor(e) === e && e
  }}
/>

但它仅适用于纯 js(无类型检查)。使用 TS 时出现类型错误(带有“e:number”):

No overload matches this call.
  Overload 1 of 2, '(props: LineSvgProps | Readonly<LineSvgProps>): ResponsiveLine', gave the following error.
    Type '(e: number) => number | undefined' is not assignable to type 'string | TickFormatter | undefined'.
      Type '(e: number) => number | undefined' is not assignable to type 'TickFormatter'.
        Types of parameters 'e' and 'value' are incompatible.
          Type 'string | number | Date' is not assignable to type 'number'.
            Type 'string' is not assignable to type 'number'.
  Overload 2 of 2, '(props: LineSvgProps, context: any): ResponsiveLine', gave the following error.
    Type '(e: number) => number | undefined' is not assignable to type 'string | TickFormatter | undefined'.
      Type '(e: number) => number | undefined' is not assignable to type 'TickFormatter'.ts(2769)

我无法将类型与此解决方案匹配,并且我不能使用“任何”类型,我开始相信图书馆创建者并没有在他们的图书馆中预测到这个问题;)如果有人可以帮助我解决这些问题或提出其他解决方案我会很感激的:)

标签: javascriptreactjstypescripttypesnivo-react

解决方案


这是因为您的自定义函数的签名与库所期望的签名不匹配。在这种情况下,您的函数应与以下签名匹配TickFormatter

export type TickFormatter = (value: number | string | Date) => string | number

如您所见,您的函数与库所期望的函数之间存在多种不兼容性。首先,你说你的值只能是一个数字,但图书馆说value也可以是一个string甚至是一个Date对象。其次,您的函数可以返回undefined,而库需要一个只能返回stringor的函数number

另外,就像您说的那样,any在此处使用将是一种不好的做法,因为您将暴露自己接收和使用不正确的数据类型。

这里最简单的解决方案就是重构您的自定义 Y 轴格式化程序函数并使其与库所期望的兼容。例如,如果你 100% 确定你只会在这个函数中接收数字:

const yformat = (e: number | string | Date) => {
  if (typeof e === 'number') {
    return Math.floor(e);
  } else {
    throw new Error('Unexpected value');
  }
};

推荐阅读