Chart.js icon indicating copy to clipboard operation
Chart.js copied to clipboard

Types: `scale.title` does not exist when a `legend` `onClick` handler is specified

Open StephanTLavavej opened this issue 2 years ago • 3 comments

Expected behavior

After creating a Chart, I want to update its colors dynamically. I understand that I can't directly say chart.options.scales.x.title.color because the properties starting with scales are optional. However, I expect to be able to test chart.options.scales?.x?.title?.color === undefined, and if that's false, TypeScript should allow me to assign a new color to chart.options.scales.x.title.color.

Current behavior

Under certain conditions, TypeScript 4.7.4 emits an error when I try to access title:

Property 'title' does not exist on type '_DeepPartialObject<{ type: "linear"; } & CartesianScaleOptions & { beginAtZero: boolean; suggestedMin?: number | undefined; suggestedMax?: number | undefined; grace?: string | number | undefined; ticks: { ...; }; }> | ... 4 more ... | _DeepPartialObject<...>'.
  Property 'title' does not exist on type '_DeepPartialObject<{ type: "radialLinear"; } & CoreScaleOptions & { animate: boolean; startAngle: number; angleLines: { display: boolean; color: Scriptable<Color, ScriptableScaleContext>; lineWidth: Scriptable<...>; borderDash: Scriptable<...>; borderDashOffset: Scriptable<...>; }; ... 7 more ...; ticks: RadialTickO...'.

The conditions appear to be:

  • A legend onClick handler is specified.
  • The error goes away if I change the handler's third parameter from LegendElement<ChartType> to any.
  • The error goes away if I omit the handler entirely.
  • The error never happens with ticks, only with title. I am not sure why title is special.

Reproducible sample

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgYQBYENYBoUdgUQDcBTAOxhzUxgBUBPMYnAGWIHMyATfAG2JDIU4rDqU4BJGPxxR2wAM5So6AEZ95cAL5wAZlAgg4AcgDGeGADoAVvKMBuALAAoKrAuy2CpQAoLfj17EymrE8gCUjk7OOgCupCYwwBCkcHyinAD6JjzAJgDWGRhifFDeGcQk5ABcuNREgjgZaVwZwFIgNSJcktJwTexcnQNivPyCADyutAzEAHxhiJrOzibJinCK6DAx8lnmcAC8cKTEAO61sN5Gm9vyU0Y4CM5wL3AwMzVGOScPz6+cW3QNSeTleYLgAJg6HkxBg8hqAG0-uDwSCUej-oDEciMbikAAPGoARgADDg6DUACxaLA43Hogk1ABMZLgFLgAE4aXT6ai4IS4ABmVnsokANm5oN5YIAurSpdKXjxVMQeJ8TFtbPLpZptei5TjdTiIGBEmtgTyXmAeDFPKR4YhLeDmmILQrFclkDl8jUXZlsrkCkVOCU9fSje6wRGMfINeo3dKBWjFS93oxPt9iJgjHBoXBVvaKE6MYkYHwEynwaseNBPgBiQWNpu-SOVzgKa3odkwKAxJjF3lSfEwT4CCCnFuVyVTxL5B3Jqcvau14wNpuNyeV6O87f09kIXfgw8RzQRZZOAvrWPoPiHDZQ257agWE1m+0Wa-qAD8FnxkWcwA6HA3ifsQhwHEccScMQOjACcnBwAAPohGxxsQFilreEGQWIMFwcQCHIahN7obOeQaNhcBQXh8ELAubyoPo5wnOc+BQPopRGAA6gA8jxABiRhnk4SxRE4oEYW0fAWMuUB3kYdb8fxJIqSS9jOBJZHyDJEA1nJRwKapJJKepYk3DsT5uDEYCQsQ3jCUAA

Optional extra steps/info to reproduce

Here's a CodePen (with TypeScript types commented out), showing that this works at runtime: https://codepen.io/StephanTLavavej/pen/GRxKJgz

TypeScript examples:

Possible solution

No response

Context

I'm implementing dark mode for the microsoft/STL Status Chart at https://microsoft.github.io/STL/ . I converted it to use TypeScript a couple of months ago, but haven't tried to change colors dynamically until now.

chart.js version

v3.8.0

Browser name and version

Chrome 103.0.5060.53

Link to your project

No response

StephanTLavavej avatar Jun 26 '22 05:06 StephanTLavavej

What I think happens is that the legend causes the type of the scale to be any of the scales. Since the RadialLinearScaleOptions don't have a title, this error appears. https://github.com/chartjs/Chart.js/blob/master/types/index.esm.d.ts#L3345-L3456

I was able to resolve the error by changing the type definition for the 3rd argument of the legend callback to _legend: LegendElement<'line'>. If your chart is always a line chart this seems like the correct solution.

Another option is to make the click handler an arrow function onClick: (_event, _legend_item, _legend) => {} and then the types for all 3 arguments appear automatically

etimberg avatar Jun 26 '22 13:06 etimberg

Thanks! I have both 'line' and 'bar' | 'line' charts, which made things more complicated, but I was able to get this working.

StephanTLavavej avatar Jun 26 '22 20:06 StephanTLavavej

I think 'bar' | line'` should be fine since those are both cartesian charts and thus can use the same axis types.

etimberg avatar Jun 26 '22 21:06 etimberg