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

如何检查联合类型参数类型并实现Chart.js数据转换?

问题描述

我们定义了如下图表数据类型:

type 1DChartPoint = { x: number }
type 2DChartPoint = 1DChartPoint & { y: number }
type 3DChartPoint = 2DChartPoint & { z: number }

type DataSet<T extends 1DChartPoint> = { data: number[] | T[] }

type BarChartDataSet = DataSet<1DChartPoint>
type ScatterplotDataSet = DataSet<2DChartPoint>
type BubbleplotDataSet = DataSet<3DChartPoint>

需要实现一个转换方法,将任意DataSet转换为Chart.js的ChartData对象,当前的转换代码存在类型检查逻辑错误:

private convert<T extends 1DChartPoint>(data: DataSet<T>) {
  let convertedData;

  if (data is number[]) {
    convertedData = data
  } else if (data is 1DChartPoint) {
    convertedData = data.map(val => val.x);
  }

  const result: chartjs.ChartData = {
    datasets: [convertedData]
  }

return result;
}

请问如何正确判断data.data是number[]还是1DChartPoint[]类型,并完成正确的转换?

解决方案

核心问题修正

原代码的错误在于:

  • 混淆了DataSet类型本身和其内部的data属性,参数data是DataSet对象,而非直接的数组/点对象
  • TypeScript中不能直接用data is number[]这类语法做类型判断,需要自定义类型守卫函数来实现准确的类型检查

实现步骤与代码

  1. 定义类型守卫函数,用于判断数组类型
  2. 提取DataSet中的data属性进行检查
  3. 根据类型执行对应转换逻辑

完整代码:

// 类型守卫:判断是否为number数组
function isNumberArray(arr: unknown): arr is number[] {
  return Array.isArray(arr) && arr.every(item => typeof item === 'number');
}

// 类型守卫:判断是否为1DChartPoint数组
function is1DChartPointArray<T extends 1DChartPoint>(arr: unknown): arr is T[] {
  return Array.isArray(arr) && arr.every(item => 
    typeof item === 'object' && 
    item !== null && 
    'x' in item && 
    typeof item.x === 'number'
  );
}

private convert<T extends 1DChartPoint>(dataSet: DataSet<T>): chartjs.ChartData {
  let convertedData: number[];
  const targetData = dataSet.data;

  if (isNumberArray(targetData)) {
    convertedData = targetData;
  } else if (is1DChartPointArray(targetData)) {
    convertedData = targetData.map(point => point.x);
  } else {
    // 处理非法数据,可根据业务需求抛出错误或返回空数组
    convertedData = [];
  }

  // Chart.js的ChartData中datasets每个元素需是包含data属性的对象
  return {
    datasets: [{
      data: convertedData
    }]
  };
}

关键说明

  • 类型守卫函数:通过is关键字定义返回类型,让TypeScript在类型检查时能识别判断后的类型,避免类型报错
  • 数组判断逻辑:先用Array.isArray确认是数组,再用every校验每个元素的类型/结构,确保整个数组符合目标类型
  • ChartData结构修正:原代码直接将convertedData放入datasets数组不符合Chart.js规范,需要包装为{ data: convertedData }的数据集对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 19:44:53