Skip to content

Conversation

@anshukushwaha07
Copy link
Contributor

This PR updates the TypeScript definition for Point to allow null values for x and y.

According to the Chart.js documentation, null is valid for skipped values in line charts. However, the current typings only accept number, which causes TypeScript errors when using null in datasets.

Before

export interface Point {
  x: number;
  y: number;
 }

After

export interface Point {
  x: number | null;
  y: number | null;
}

Example

new Chart<'line'>(ctx, {
  type: 'line',
  data: {
    datasets: [
      {
        data: [
          { x: 10, y: 20 },
          { x: 15, y: null }, //  now type checks correctly
          { x: 20, y: 10 }
        ]
      }
    ]
  }
});

Why this change is needed

  • Runtime behavior already supports null (point is skipped).
  • Docs confirm null is valid.
  • TypeScript definitions should align with runtime and docs.
  • Fixes TypeScript error: Type 'null' is not assignable to type 'number'

@LeeLenaleee LeeLenaleee added the type: types Typescript type changes label Sep 11, 2025
@LeeLenaleee LeeLenaleee added this to the Version 4.5.1 milestone Sep 11, 2025
Copy link
Contributor Author

@anshukushwaha07 anshukushwaha07 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @LeeLenaleee , I’ve applied the suggested changes. Please re-review.

@LeeLenaleee LeeLenaleee merged commit a5262b1 into chartjs:master Sep 16, 2025
8 of 9 checks passed
@johanrd
Copy link

johanrd commented Oct 13, 2025

I had a type regression with the release 4.5.1, and went here to check.

The link in the PR description (https://www.chartjs.org/docs/latest/charts/line.html#missing-data) says that null is valid for skipped values in line charts., but the link does not lead to a section missing-data, nor do I find a relevant section stating the above. Can you please help me with an updated link? thanks!

@LeeLenaleee
Copy link
Collaborator

It says it here in the spangaps property:
https://www.chartjs.org/docs/4.5.0/charts/line.html#line-styling

image

@johanrd
Copy link

johanrd commented Oct 13, 2025

@LeeLenaleee thanks!

@johanrd
Copy link

johanrd commented Oct 13, 2025

Okay, this may lead to regressions for others as well. Posting here in case this is relevant to others. This used to work:

import { MatrixController, MatrixElement } from 'chartjs-chart-matrix'
Chart.register(MatrixController, MatrixElement)

function matrixChartOptions(): ChartOptions<'matrix'> { 
  return {} 
}

const myChartOptions: ChartOptions = matrixChartOptions()

But does now throw type error:

Type '_DeepPartialObject<CoreChartOptions<"matrix"> & ElementChartOptions<"matrix"> & PluginChartOptions<"matrix"> & DatasetChartOptions<"matrix"> & ScaleChartOptions<...>>' is not assignable to type '_DeepPartialObject<CoreChartOptions<keyof ChartTypeRegistry> & ElementChartOptions<keyof ChartTypeRegistry> & PluginChartOptions<...> & DatasetChartOptions<...> & ScaleChartOptions<...>>'.
  Types of property 'color' are incompatible.
    Type 'string | _DeepPartialObject<CanvasGradient> | _DeepPartialObject<CanvasPattern> | ((ctx: ScriptableContext<"matrix">, options: AnyObject) => Color | undefined) | undefined' is not assignable to type 'string | _DeepPartialObject<CanvasGradient> | _DeepPartialObject<CanvasPattern> | ((ctx: ScriptableContext<keyof ChartTypeRegistry>, options: AnyObject) => Color | undefined) | undefined'.
      Type '(ctx: ScriptableContext<"matrix">, options: AnyObject) => Color | undefined' is not assignable to type 'string | _DeepPartialObject<CanvasGradient> | _DeepPartialObject<CanvasPattern> | ((ctx: ScriptableContext<keyof ChartTypeRegistry>, options: AnyObject) => Color | undefined) | undefined'.
        Type '(ctx: ScriptableContext<"matrix">, options: AnyObject) => Color | undefined' is not assignable to type '(ctx: ScriptableContext<keyof ChartTypeRegistry>, options: AnyObject) => Color | undefined'.
          Types of parameters 'ctx' and 'ctx' are incompatible.
            Type 'ScriptableContext<keyof ChartTypeRegistry>' is not assignable to type 'ScriptableContext<"matrix">'.
              Types of property 'dataset' are incompatible.
                Type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & ... 9 more ... & _DeepPartialObject<...>' is not assignable to type '_DeepPartialObject<{ type: "matrix"; } & MatrixControllerDatasetOptions> & _DeepPartialObject<PluginDatasetOptionsByType<"matrix">> & ChartDatasetProperties<...>'.
                  Type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & ... 9 more ... & _DeepPartialObject<...>' is not assignable to type '_DeepPartialObject<PluginDatasetOptionsByType<"matrix">>'.
                    Types of property 'tooltip' are incompatible.
                      Type '_DeepPartialObject<TooltipDatasetOptions<keyof ChartTypeRegistry>> | undefined' is not assignable to type '_DeepPartialObject<TooltipDatasetOptions<"matrix">> | undefined'.
                        Type '_DeepPartialObject<TooltipDatasetOptions<keyof ChartTypeRegistry>>' is not assignable to type '_DeepPartialObject<TooltipDatasetOptions<"matrix">>'.
                          Types of property 'callbacks' are incompatible.
                            Type '_DeepPartialObject<TooltipDatasetCallbacks<keyof ChartTypeRegistry, TooltipModel<keyof ChartTypeRegistry>, TooltipItem<keyof ChartTypeRegistry>>> | undefined' is not assignable to type '_DeepPartialObject<TooltipDatasetCallbacks<"matrix", TooltipModel<"matrix">, TooltipItem<"matrix">>> | undefined'.
                              Type '_DeepPartialObject<TooltipDatasetCallbacks<keyof ChartTypeRegistry, TooltipModel<keyof ChartTypeRegistry>, TooltipItem<keyof ChartTypeRegistry>>>' is not assignable to type '_DeepPartialObject<TooltipDatasetCallbacks<"matrix", TooltipModel<"matrix">, TooltipItem<"matrix">>>'.
                                Types of property 'beforeLabel' are incompatible.
                                  Type '((this: TooltipModel<keyof ChartTypeRegistry>, tooltipItem: TooltipItem<keyof ChartTypeRegistry>) => string | ... 1 more ... | string[]) | undefined' is not assignable to type '((this: TooltipModel<"matrix">, tooltipItem: TooltipItem<"matrix">) => string | void | string[]) | undefined'.
                                    Type '(this: TooltipModel<keyof ChartTypeRegistry>, tooltipItem: TooltipItem<keyof ChartTypeRegistry>) => string | ... 1 more ... | string[]' is not assignable to type '(this: TooltipModel<"matrix">, tooltipItem: TooltipItem<"matrix">) => string | void | string[]'.
                                      The 'this' types of each signature are incompatible.
                                        Type 'TooltipModel<"matrix">' is not assignable to type 'TooltipModel<keyof ChartTypeRegistry>'.
                                          The types of 'chart.config' are incompatible between these types.
                                            Type 'ChartConfiguration<"matrix", MatrixDataPoint[], unknown> | ChartConfigurationCustomTypesPerDataset<"matrix", MatrixDataPoint[], unknown>' is not assignable to type 'ChartConfiguration<keyof ChartTypeRegistry, (number | Point | [number, number] | BubbleDataPoint | MatrixDataPoint | null)[], unknown> | ChartConfigurationCustomTypesPerDataset<...>'.
                                              Type 'ChartConfiguration<"matrix", MatrixDataPoint[], unknown>' is not assignable to type 'ChartConfiguration<keyof ChartTypeRegistry, (number | Point | [number, number] | BubbleDataPoint | MatrixDataPoint | null)[], unknown> | ChartConfigurationCustomTypesPerDataset<...>'.
                                                Type 'ChartConfiguration<"matrix", MatrixDataPoint[], unknown>' is not assignable to type 'ChartConfiguration<keyof ChartTypeRegistry, (number | Point | [number, number] | BubbleDataPoint | MatrixDataPoint | null)[], unknown>'.
                                                  Types of property 'options' are incompatible.
                                                    Type '_DeepPartialObject<CoreChartOptions<"matrix"> & ElementChartOptions<"matrix"> & PluginChartOptions<"matrix"> & DatasetChartOptions<"matrix"> & ScaleChartOptions<...>> | undefined' is not assignable to type '_DeepPartialObject<CoreChartOptions<keyof ChartTypeRegistry> & ElementChartOptions<keyof ChartTypeRegistry> & PluginChartOptions<...> & DatasetChartOptions<...> & ScaleChartOptions<...>> | undefined'.
                                                      Type '_DeepPartialObject<CoreChartOptions<"matrix"> & ElementChartOptions<"matrix"> & PluginChartOptions<"matrix"> & DatasetChartOptions<"matrix"> & ScaleChartOptions<...>>' is not assignable to type '_DeepPartialObject<CoreChartOptions<keyof ChartTypeRegistry> & ElementChartOptions<keyof ChartTypeRegistry> & PluginChartOptions<...> & DatasetChartOptions<...> & ScaleChartOptions<...>>'.
                                                        Types of property 'animation' are incompatible.
                                                          Type 'false | _DeepPartialObject<AnimationSpec<"matrix"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | ... 4 more ... | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<keyof ChartTypeRegistry> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | ... 4 more ... | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
                                                            Type '_DeepPartialObject<AnimationSpec<"matrix"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | Point | [...] | BubbleDataPoint | MatrixDataPoint | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<keyof ChartTypeRegistry> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | ... 4 more ... | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
                                                              Type '_DeepPartialObject<AnimationSpec<"matrix"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | Point | [...] | BubbleDataPoint | MatrixDataPoint | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>' is not assignable to type '_DeepPartialObject<AnimationSpec<keyof ChartTypeRegistry> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | ... 4 more ... | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>'.
                                                                Types of property 'duration' are incompatible.
                                                                  Type 'number | ((ctx: ScriptableContext<"matrix">, options: AnyObject) => number | undefined) | undefined' is not assignable to type 'number | ((ctx: ScriptableContext<keyof ChartTypeRegistry>, options: AnyObject) => number | undefined) | undefined'.
                                                                    Type '(ctx: ScriptableContext<"matrix">, options: AnyObject) => number | undefined' is not assignable to type 'number | ((ctx: ScriptableContext<keyof ChartTypeRegistry>, options: AnyObject) => number | undefined) | undefined'.
                                                                      Type '(ctx: ScriptableContext<"matrix">, options: AnyObject) => number | undefined' is not assignable to type '(ctx: ScriptableContext<keyof ChartTypeRegistry>, options: AnyObject) => number | undefined'.
                                                                        Types of parameters 'ctx' and 'ctx' are incompatible.
                                                                          Type 'ScriptableContext<keyof ChartTypeRegistry>' is not assignable to type 'ScriptableContext<"matrix">'.
                                                                            Types of property 'dataset' are incompatible.
                                                                              Type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & ... 9 more ... & _DeepPartialObject<...>' is not assignable to type '_DeepPartialObject<{ type: "matrix"; } & MatrixControllerDatasetOptions> & _DeepPartialObject<PluginDatasetOptionsByType<"matrix">> & ChartDatasetProperties<...>'.
                                                                                Type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & ... 9 more ... & _DeepPartialObject<...>' is not assignable to type 'ChartDatasetProperties<"matrix", MatrixDataPoint[]>'.
                                                                                  Types of property 'data' are incompatible.
                                                                                    Type '(number | Point | [number, number] | BubbleDataPoint | MatrixDataPoint | null)[]' is not assignable to type 'MatrixDataPoint[]'.
                                                                                      Type 'number | Point | [number, number] | BubbleDataPoint | MatrixDataPoint | null' is not assignable to type 'MatrixDataPoint'.
                                                                                        Type 'null' is not assignable to type 'MatrixDataPoint'.ts-

This seems to be because ChartJs-matrix uses the Element type from core.element.d.ts? not sure:

Screenshot 2025-10-13 at 15 15 04

@HerrDerb
Copy link

HerrDerb commented Oct 15, 2025

As this breaks probably quite a few projects due missing nullable checks, it might have been more appropriate to place this change within a minor release instead of a bugfix.

@LeeLenaleee @etimberg
In general this seems like a questionable approach. A skipped point should be inserted as null itself instead of a point with null values. This feels like chartjs is trying to handle badly prepared data, instead putting the dev using the library in responsibility

@n19htz
Copy link

n19htz commented Oct 16, 2025

it's actually a breaking change, why did you release it as a patch? A lot of projects won't build cuz of this change.

@LeeLenaleee
Copy link
Collaborator

I can see why you see this as breaking, but the old implementation was breaking on runtime, now the developer is forced to handle this so it won't break on runtime.

@etimberg what do we want to do with this, keep it or revert it since it is causing problems for others?

@etimberg
Copy link
Member

I think we should keep it, since as you mentioned there were silent runtime errors before

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: types Typescript type changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants