如何在不修改index.esm.d.ts的情况下为Chart.js折线图实现自定义数据集结构
解决Angular中ng2-charts自定义数据集的TypeScript类型错误问题
问题场景
在Angular项目中使用ng2-charts实现Chart.js折线图时,希望采用如下自定义嵌套结构的数据集:
data: [ {id: '1', nested: {value: 500, extra: 'one'}}, {id: '2', nested: {value: 1500, extra: 'two'}}, ]
当前项目依赖版本:
"@angular/core": "^14.2.0" "@types/chart.js": "^2.9.37" "chart.js": "^3.9.1" "ng2-charts": "^4.0.1" "typescript": "~4.7.2" "tslib": "^2.3.0"
实现过程中触发TypeScript类型错误:
error TS2322: Type '{ id: string; nested: { value: number; extra: string; }; }' is not assignable to type 'number | ScatterDataPoint | BubbleDataPoint | null'.
需求是不修改库自带的index.esm.d.ts类型文件,实现自定义数据集结构。
解决方案
方法1:使用类型断言快速解决
直接对数据集进行类型断言,明确告知TypeScript该数据的类型合法性。可以选择断言为any[],或者定义更精准的自定义接口后断言:
方式1-1:断言为any[]
修改组件中数据集的定义:
this.chartData.datasets = [ { data: [ {id: '1', nested: {value: 500, extra: 'one'}}, {id: '2', nested: {value: 1500, extra: 'two'}}, ] as any[], // 添加类型断言 label: 'set 1', borderColor: '#3cba9f', fill: false, } ]
方式1-2:自定义接口后断言
先定义匹配数据集结构的接口,再进行断言,保留类型检查的部分优势:
// 在组件内定义自定义数据点接口 interface CustomDataPoint { id: string; nested: { value: number; extra: string; }; } // 初始化数据集时断言 this.chartData.datasets = [ { data: [ {id: '1', nested: {value: 500, extra: 'one'}}, {id: '2', nested: {value: 1500, extra: 'two'}}, ] as CustomDataPoint[], label: 'set 1', borderColor: '#3cba9f', fill: false, } ]
方法2:扩展Chart.js类型定义(推荐)
通过创建本地类型声明文件扩展Chart.js的类型系统,无需修改库源文件,同时保留完整的类型检查:
- 在项目
src目录下创建typings/chartjs文件夹,新建index.d.ts文件 - 在文件中扩展Chart.js的类型:
import { ChartTypeRegistry, LineControllerDatasetOptions } from 'chart.js'; declare module 'chart.js' { // 定义自定义数据点类型 interface CustomDataPoint { id: string; nested: { value: number; extra: string; }; } // 扩展折线图的数据点类型 interface ChartTypeRegistry { line: { datasetOptions: LineControllerDatasetOptions; dataPoint: CustomDataPoint | number | ScatterDataPoint | null; }; } }
- 修改
tsconfig.json,确保自定义类型文件被编译器识别:
{ "compilerOptions": { "typeRoots": [ "./node_modules/@types", "./src/typings" ] } }
完成后,TypeScript会自动识别扩展的类型,无需额外断言即可使用自定义数据集。
方法3:使用unknown类型安全转换
先将数据转为unknown类型,再转为Chart.js期望的联合类型,比直接使用any更安全:
const customData = [ {id: '1', nested: {value: 500, extra: 'one'}}, {id: '2', nested: {value: 1500, extra: 'two'}}, ]; this.chartData.datasets = [ { data: customData as unknown as (number | ScatterDataPoint | BubbleDataPoint | null)[], label: 'set 1', borderColor: '#3cba9f', fill: false, } ]
内容的提问来源于stack exchange,提问作者CJay Horton
相关产品推荐
相关产品推荐

