You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3.js类型错误排查:垂直柱状图构建时的TS2345报错问题

解决D3.js + TypeScript构建柱状图的TS2345错误

错误原因

TypeScript报错是因为d3.scaleBand的scale函数在传入不在定义域内的键时会返回undefined——尽管你的数据中period_ended_at已全部加入x轴定义域,但TypeScript无法静态推断这一点,因此判定返回值可能为number | undefined,而D3的.attr()方法不接受undefined作为属性值。

另外,d3.max在数据为空数组时会返回undefined,这也会导致y轴定义域的类型问题,间接影响后续y_scale的调用。

修复方案

1. 处理x轴scale的undefined返回值

调用x_scale时,用**非空断言运算符!**告知TypeScript该值一定存在,或提供默认值兜底:

// 非空断言(适用于确定数据都在定义域内的场景)
.attr("x", (d) => x_scale(d.period_ended_at)!)

// 或默认值写法(更安全)
.attr("x", (d) => x_scale(d.period_ended_at) ?? 0)

2. 修复y轴定义域的潜在undefined问题

给d3.max添加默认值,确保定义域是有效的数值范围:

y_scale.domain([0, d3.max(data, (d) => d.price_cents) ?? 0]);

3. 可选:给scale添加类型标注

显式标注scale的输入输出类型,让TypeScript类型推断更精准:

const x_scale = d3.scaleBand<string>() // 指定输入为string类型
  .range([0, width])
  .padding(0.1);

const y_scale = d3.scaleLinear<number, number>() // 指定输入输出为number类型
  .range([height, 0]);

完整修复后的代码

type Analytics = {
  id: number;
  period_ended_at: string;
  price_cents: number;
  fee_cents: number;
};

const data: Analytics[] = await get_data()

const width = 600
const height = 400

const x_scale = d3.scaleBand<string>()
  .range([0, width])
  .padding(0.1);
const y_scale = d3.scaleLinear<number, number>()
  .range([height, 0]);

const svg = d3.select(".chart")
  .append("svg")
  .attr("width", width)
  .attr("height", height)
  .style("border", "1px solid black")

x_scale.domain(data.map((d) => d.period_ended_at));
y_scale.domain([0, d3.max(data, (d) => d.price_cents) ?? 0]);

svg
  .selectAll("rect")
  .data(data)
  .join("rect")
  .attr("class", "bar")
  .attr("x", (d) => x_scale(d.period_ended_at)!)
  .attr("y", (d) => y_scale(d.price_cents)!)
  .attr("width", x_scale.bandwidth())
  .attr("height", (d) => height - y_scale(d.price_cents)!);

内容的提问来源于stack exchange,提问作者SoupeChinoise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 05:22:33