Skip to content

Typehinting ChartOptions seems broken for pie and doughnut #10896

@DrowningElysium

Description

@DrowningElysium

Expected behavior

I type hint ChartOptions or ChartOptions<ChartType> for a function and then pass a typehint of ChartOptions<'pie'> or ChartOptions<'doughnut'> .

Donut.vue:

<template>
    <Base
        :height="height"
        :width="width"
        :chart-options="chartOptions"
        :chart-data="chartData"
        chart-type="doughnut"
    />
</template>

<script setup lang="ts">
import {
    ArcElement,
    Chart,
    ChartData,
    ChartOptions,
    DoughnutController,
    Legend,
    Tooltip,
} from 'chart.js';
import Base from './Base.vue';

Chart.register(DoughnutController, ArcElement, Legend, Tooltip);

interface Props {
    chartData: ChartData<'doughnut', unknown[]>;
    chartOptions: ChartOptions<'doughnut'>;
    width?: number;
    height?: number;
}

withDefaults(
    defineProps<Props>(),
    {
        width: 200,
        height: 200,
    },
);
</script>

The props typehinting in Base.vue:

import {
    Chart,
    ChartData,
    ChartOptions,
    ChartType,
} from 'chart.js';
import {onBeforeUnmount, onMounted, ref, watch} from 'vue';

interface Props {
    chartType: ChartType;
    chartData: ChartData<ChartType, unknown[]>;
    chartOptions: ChartOptions<ChartType>;
    width: number;
    height: number;
    chartId?: number;
}

const props = withDefaults(
    defineProps<Props>(),
    {
        chartId: () => {
            // @ts-ignore this way it's global
            if (!window.chartId) window.chartId = 0;
            // @ts-ignore this way it's global
            return ++window.chartId;
        },
    },
);

Current behavior

I get the following error in vue-tsc:

resources/js/components/chart/Donut.vue:5:9 - error TS2322: Type '_DeepPartialObject<CoreChartOptions<"doughnut"> & ElementChartOptions<"doughnut"> & PluginChartOptions<"doughnut"> & DatasetChartOptions<"doughnut"> & ScaleChartOptions<...> & DoughnutControllerChartOptions>' is not assignable to type '_DeepPartialObject<CoreChartOptions<keyof ChartTypeRegistry> & ElementChartOptions<keyof ChartTypeRegistry> & PluginChartOptions<...> & DatasetChartOptions<...> & ScaleChartOptions<...>>'.
  Types of property 'animation' are incompatible.
    Type 'false | _DeepPartialObject<false & DoughnutAnimationOptions> | _DeepPartialObject<AnimationSpec<"doughnut"> & { onProgress?: ((this: Chart$4<...>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart$4<...>, event: AnimationEvent) => void) | undefined; } & false> | _DeepPartialObject<...> | undefi...' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<keyof ChartTypeRegistry> & { onProgress?: ((this: Chart$4<keyof ChartTypeRegistry, (number | ... 3 more ... | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart$4<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.
      Type '_DeepPartialObject<false & DoughnutAnimationOptions>' is not assignable to type 'false | _DeepPartialObject<AnimationSpec<keyof ChartTypeRegistry> & { onProgress?: ((this: Chart$4<keyof ChartTypeRegistry, (number | ... 3 more ... | null)[], unknown>, event: AnimationEvent) => void) | undefined; onComplete?: ((this: Chart$4<...>, event: AnimationEvent) => void) | undefined; }> | undefined'.

5         :chart-options="chartOptions"
          ~~~~~~~~~~~~~

  resources/js/components/chart/Base.vue:19:5
    19     chartOptions: ChartOptions<ChartType>;
           ~~~~~~~~~~~~
    The expected type comes from property 'chartOptions' which is declared here on type 'ComponentProps<ComponentPublicInstanceConstructor<{ $: ComponentInternalInstance; $data: {}; $props: Partial<{ chartId: number; }> & Omit<Readonly<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<Props>, { ...; }>>> & VNodeProps & AllowedComponentProps & ComponentCustomProps, "chartId">; ... 10 more...'

Reproducible sample

Code provided in current behaviour

Optional extra steps/info to reproduce

No response

Possible solution

I couldn't find the reason why animation seems to not be compatible. However I did notice that in some areas animation is typehinted as:

  • animation: false | DoughnutAnimationOptions;
  • animation: false | PolarAreaAnimationOptions;
  • animation: AnimationSpec<TType>; This might be the cause?
  • Or the next could be the cause too
animation: false | AnimationSpec<TType> & {
    /**
     * Callback called on each step of an animation.
     */
    onProgress?: (this: Chart$4, event: AnimationEvent) => void;
    /**
     * Callback called when all animations are completed.
     */
    onComplete?: (this: Chart$4, event: AnimationEvent) => void;
  };
  • animation: AnimationSpec<TType> | false;

Context

No response

chart.js version

v4.0.1

Browser name and version

No response

Link to your project

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions