Skip to content

[REGRESSION 6.0.2->7.0.2] Type T<A> not assignable to T<A|B> #63733

Closed as not planned

Description

🔎 Search Terms

Issue from #63644

🕗 Version & Regression Information

  • This changed between versions 6.0.2 and 7.0.2

⏯ Playground Link

No response

💻 Code

import {ChartDataset, ChartTypeRegistry} from "chart.js"

const a: ChartDataset<keyof ChartTypeRegistry> = {} as ChartDataset<"scatter">;

🙁 Actual behavior

In TS 7.0.2

test.ts:3:7 - error TS2322: Type 'ChartDataset<"scatter">' is not assignable to type 'ChartDataset<keyof ChartTypeRegistry>'.
  Type 'ChartDataset<"scatter">' is not assignable to type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>'.
    Type 'ChartDataset<"scatter">' is not assignable to type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions>'.
      Types of property 'animation' are incompatible.
        Type 'false | _DeepPartialObject<AnimationSpec<"line"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<"radar"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
          Type '_DeepPartialObject<AnimationSpec<"line"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<"radar"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
            Type '_DeepPartialObject<AnimationSpec<"line"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>' is not assignable to type '_DeepPartialObject<AnimationSpec<"radar"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>'.
              Types of property 'duration' are incompatible.
                Type 'number | ((ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined) | undefined' is not assignable to type 'number | ((ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined) | undefined'.
                  Type '(ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined' is not assignable to type 'number | ((ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined) | undefined'.
                    Type '(ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined' is not assignable to type '(ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined'.
                      Types of parameters 'ctx' and 'ctx' are incompatible.
                        Type 'ScriptableContext<"radar">' is not assignable to type 'ScriptableContext<"line">'.
                          Types of property 'dataset' are incompatible.
                            Type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>' is not assignable to type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>'.
                              Type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>' is not assignable to type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions>'.
                                Types of property 'animation' are incompatible.
                                  Type 'false | _DeepPartialObject<AnimationSpec<"radar"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<"line"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
                                    Type '_DeepPartialObject<AnimationSpec<"radar"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<"line"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
                                      Type '_DeepPartialObject<AnimationSpec<"radar"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>' is not assignable to type '_DeepPartialObject<AnimationSpec<"line"> & { onProgress?: ((this: Chart<keyof ChartTypeRegistry, (number | BubbleDataPoint | Point | [...] | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart<...>, event: AnimationEvent) => void) | undefined; }>'.
                                        Types of property 'duration' are incompatible.
                                          Type 'number | ((ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined) | undefined' is not assignable to type 'number | ((ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined) | undefined'.
                                            Type '(ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined' is not assignable to type 'number | ((ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined) | undefined'.
                                              Type '(ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined' is not assignable to type '(ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined'.
                                                Types of parameters 'ctx' and 'ctx' are incompatible.
                                                  Type 'ScriptableContext<"line">' is not assignable to type 'ScriptableContext<"radar">'.
                                                    Types of property 'dataset' are incompatible.
                                                      Type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>' is not assignable to type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>'.
                                                        Type '_DeepPartialObject<{ type: "line"; } & LineControllerDatasetOptions & FillerControllerDatasetOptions> & _DeepPartialObject<...> & ChartDatasetProperties<...>' is not assignable to type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions>'.
                                                          Types of property 'borderWidth' are incompatible.
                                                            Type 'number | readonly (number | undefined)[] | ((ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined) | undefined' is not assignable to type 'number | readonly (number | undefined)[] | ((ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined) | undefined'.
                                                              Type '(ctx: ScriptableContext<"line">, options: AnyObject) => number | undefined' is not assignable to type 'number | readonly (number | undefined)[] | ((ctx: ScriptableContext<"radar">, options: AnyObject) => number | undefined) | undefined'.

3 const a: ChartDataset<keyof ChartTypeRegistry> = {} as ChartDataset<"scatter">;
        ~


Found 1 error in test.ts:3

🙂 Expected behavior

No errors, like in TS 6.0.2.

Additional information about the issue

  • chart.js version 4.5.1
  • both TS version executed with tsc $file --ignoreConfig.

keyof ChartTypeRegistry is "bar"|"line"|"scatter"|"bubble"|"pie"|"doughnut"|"polarArea"|"radar".
So "scatter" is assignable to keyof ChartTypeRegistry.

In TS 6.0.2, ChartDataset<"scatter"> is resolved as:

_DeepPartialObject<{type: "scatter";} & LineControllerDatasetOptions>
& _DeepPartialObject<PluginDatasetOptionsByType<"scatter">> & ChartDatasetProperties<"scatter", (number | Point | null)[]>

And ChartDataset<keyof ChartTypeRegistry> is resolved as:

(               _DeepPartialObject<{type: "bar";} & BarControllerDatasetOptions>
              | _DeepPartialObject<{type: "line";} & LineControllerDatasetOptions & FillerControllerDatasetOptions>
              | _DeepPartialObject<{type: "scatter";} & LineControllerDatasetOptions>
              | _DeepPartialObject<{type: "bubble";} & BubbleControllerDatasetOptions>
              | _DeepPartialObject<...> | _DeepPartialObject<...> | _DeepPartialObject<...> | _DeepPartialObject<...>
) & _DeepPartialObject<...> & ChartDatasetProperties<...>

For unknown reasons, TS 7.0.2 is trying to compare ChartDataset<"scatter"> and ChartDataset<"radar">:

Type 'ChartDataset<"scatter">' is not assignable to type '_DeepPartialObject<{ type: "radar"; } & RadarControllerDatasetOptions & FillerControllerDatasetOptions>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.

For reference:

export interface ChartTypeRegistry {
  bar: {
    chartOptions: BarControllerChartOptions;
    datasetOptions: BarControllerDatasetOptions;
    defaultDataPoint: number | [number, number] | null;
    metaExtensions: {};
    parsedDataType: BarParsedData,
    scales: keyof CartesianScaleTypeRegistry;
  };
  line: {
    chartOptions: LineControllerChartOptions;
    datasetOptions: LineControllerDatasetOptions & FillerControllerDatasetOptions;
    defaultDataPoint: ScatterDataPoint | number | null;
    metaExtensions: {};
    parsedDataType: CartesianParsedData;
    scales: keyof CartesianScaleTypeRegistry;
  };
  scatter: {
    chartOptions: ScatterControllerChartOptions;
    datasetOptions: ScatterControllerDatasetOptions;
    defaultDataPoint: ScatterDataPoint | number | null;
    metaExtensions: {};
    parsedDataType: CartesianParsedData;
    scales: keyof CartesianScaleTypeRegistry;
  };
  bubble: {
    chartOptions: unknown;
    datasetOptions: BubbleControllerDatasetOptions;
    defaultDataPoint: BubbleDataPoint;
    metaExtensions: {};
    parsedDataType: BubbleParsedData;
    scales: keyof CartesianScaleTypeRegistry;
  };
  pie: {
    chartOptions: PieControllerChartOptions;
    datasetOptions: PieControllerDatasetOptions;
    defaultDataPoint: PieDataPoint;
    metaExtensions: PieMetaExtensions;
    parsedDataType: number;
    scales: keyof CartesianScaleTypeRegistry;
  };
  doughnut: {
    chartOptions: DoughnutControllerChartOptions;
    datasetOptions: DoughnutControllerDatasetOptions;
    defaultDataPoint: DoughnutDataPoint;
    metaExtensions: DoughnutMetaExtensions;
    parsedDataType: number;
    scales: keyof CartesianScaleTypeRegistry;
  };
  polarArea: {
    chartOptions: PolarAreaControllerChartOptions;
    datasetOptions: PolarAreaControllerDatasetOptions;
    defaultDataPoint: number;
    metaExtensions: {};
    parsedDataType: RadialParsedData;
    scales: keyof RadialScaleTypeRegistry;
  };
  radar: {
    chartOptions: RadarControllerChartOptions;
    datasetOptions: RadarControllerDatasetOptions & FillerControllerDatasetOptions;
    defaultDataPoint: number | null;
    metaExtensions: {};
    parsedDataType: RadialParsedData;
    scales: keyof RadialScaleTypeRegistry;
  };
}

Activity

  1. MartinJohns commented on Aug 7, 2026

    @MartinJohns
    Contributor

    You get the same error in TypeScript 6.0 if you enable stable types ordering.

    Also you should take note that your types use UnionToIntersection, which was called unsupported by the team: #43077 (comment)

    We don't really support uses of UnionToIntersection; this operation is ill-defined.

  2. denis-migdal commented on Aug 8, 2026

    @denis-migdal
    Author

    Thanks, I declared the issue to Chart.JS.

    Is there a way to avoid UnionToIntersection ?

  3. typescript-automation commented on Aug 13, 2026

    @typescript-automation
    Contributor

    This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Not a DefectThis behavior is one of several equally-correct options

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions