From: emmcbd <42184090+emmcbd@users.noreply.github.com> Date: Sat, 12 Sep 2020 00:18:21 +0000 (+0200) Subject: Strong chart object and properties typing (#7782) X-Git-Tag: v3.0.0-beta.2~1^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7dbfde524ff1a58493c9ad077801bfb4f0d260bd;p=thirdparty%2FChart.js.git Strong chart object and properties typing (#7782) * Strong chart object and chart creation typing * Handle mixed charts * Add documentation --- diff --git a/docs/docs/developers/charts.md b/docs/docs/developers/charts.md index 385132b8e..360ec616e 100644 --- a/docs/docs/developers/charts.md +++ b/docs/docs/developers/charts.md @@ -150,3 +150,33 @@ new Chart(ctx, { options: options }); ``` + +## TypeScript Typings + +If you want your new chart type to be statically typed, you must provide a `.d.ts` TypeScript declaration file. Chart.js provides a way to augment built-in types with user-defined ones, by using the concept of "declaration merging". + +There are three main declarations that can be augmented when adding a new chart type: + +* `ChartTypeEnum` enumeration must contain an entry for the new type. +* `IChartDatasetRegistry` must contains the dataset options for the new type, either by extending `IChartDatasetBase` or an existing entry in `IChartDatasetRegistry`. +* `IChartOptionsRegistry` must contains the chart options for the new type, either by extending `IChartOptionsBase` or an existing entry in `IChartOptionsRegistry`. + +For example, to provide typings for a new chart type that extends from a bubble chart, you would add a `.d.ts` containing: + +```javascript +import { IChartDatasetRegistry, IChartOptionsRegistry } from 'chart.js' + +declare module 'chart.js' { + enum ChartTypeEnum { + derivedBubble = 'derivedBubble' + } + + interface IChartDatasetRegistry { + derivedBubble: IChartDatasetRegistry['bubble'] + } + + interface IChartOptionsRegistry { + derivedBubble: IChartOptionsRegistry['bubble'] + } +} +``` diff --git a/types/core/index.d.ts b/types/core/index.d.ts index 1739fcde7..483634438 100644 --- a/types/core/index.d.ts +++ b/types/core/index.d.ts @@ -10,7 +10,7 @@ import { TimeUnit, IEvent, } from './interfaces'; -import { IChartDataset, IChartConfiguration, ConfigurationOptions, ConfigurationData, IChartType } from '../interfaces'; +import { IChartDataset, IChartConfiguration, IChartType } from '../interfaces'; export interface IDateAdapter { /** @@ -232,16 +232,12 @@ export interface IParsingOptions { | false; } -export interface Chart< - T = unknown, - L = string, - C extends IChartConfiguration = IChartConfiguration -> { +export interface Chart { readonly platform: BasePlatform; readonly id: string; readonly canvas: HTMLCanvasElement; readonly ctx: CanvasRenderingContext2D; - readonly config: C; + readonly config: IChartConfiguration readonly width: number; readonly height: number; readonly aspectRatio: number; @@ -252,8 +248,8 @@ export interface Chart< readonly scale: Scale | undefined; readonly attached: boolean; - data: ConfigurationData; - options: ConfigurationOptions; + data: IChartConfiguration['data']; + options: IChartConfiguration['options']; clear(): this; stop(): this; @@ -301,10 +297,10 @@ export declare type ChartItem = export const Chart: { prototype: Chart; - new = IChartConfiguration>( + new ( item: ChartItem, - config: C - ): Chart; + config: IChartConfiguration + ): Chart; readonly version: string; readonly instances: { [key: string]: Chart }; diff --git a/types/interfaces.d.ts b/types/interfaces.d.ts index 27239a6e7..d7b2cf794 100644 --- a/types/interfaces.d.ts +++ b/types/interfaces.d.ts @@ -37,40 +37,6 @@ export type DeepPartial = T extends {} } : T; -export type IChartDataset = DeepPartial & { - data: T[]; -}; - -export type IBarControllerDataset = IChartDataset; -export type ILineControllerDataset = IChartDataset< - T, - ILineControllerDatasetOptions & IFillerControllerDatasetOptions ->; -export type IScatterControllerDataset = IChartDataset; -export type IBubbleControllerDataset = IChartDataset; -export type IPieControllerDataset = IChartDataset; -export type IDoughnutControllerDataset = IChartDataset; -export type IPolarAreaControllerDataset = IChartDataset; -export type IRadarControllerDataset = IChartDataset; - -export interface IChartData = IChartDataset> -{ - labels: L[]; - datasets: DS[]; -} - -export type IChartOptions = DeepPartial< - ICoreChartOptions & - IParsingOptions & - ITooltipChartOptions & - ILegendChartOptions & - ITitleChartOptions & - IChartAnimationOptions & - IScaleChartOptions & - IElementChartOptions & - O ->; - export enum ChartTypeEnum { bar = 'bar', bubble = 'bubble', @@ -84,79 +50,111 @@ export enum ChartTypeEnum { export type IChartType = keyof typeof ChartTypeEnum; -export interface IChartConfiguration< - TYPE extends IChartType = IChartType, - T = unknown, - L = string, - DS extends IChartDataset = IChartDataset, - O = {} -> { - type: TYPE; - data: IChartData; - options?: IChartOptions; - plugins?: IPlugin[]; +export interface IChartDatasetProperties { + type?: TYPE; + data: DATA; } -export type IBarControllerConfiguration = IChartConfiguration< +export type IChartDatasetBase = DeepPartial< + IControllerDatasetOptions & IParsingOptions & O +> & IChartDatasetProperties; + +export type IBarControllerDataset = IChartDatasetBase< 'bar', - T, - L, - IBarControllerDataset, - IBarControllerChartOptions + DATA, + IBarControllerDatasetOptions >; -export type ILineControllerConfiguration = IChartConfiguration< +export type ILineControllerDataset = IChartDatasetBase< 'line', - T, - L, - ILineControllerDataset, - ILineControllerChartOptions + DATA, + ILineControllerDatasetOptions & IFillerControllerDatasetOptions >; -export type IScatterControllerConfiguration = IChartConfiguration< +export type IScatterControllerDataset = IChartDatasetBase< 'scatter', - T, - L, - IScatterControllerDataset, - IScatterControllerChartOptions + DATA, + IScatterControllerDatasetOptions >; -export type IBubbleControllerConfiguration = IChartConfiguration< +export type IBubbleControllerDataset = IChartDatasetBase< 'bubble', - T, - L, - IBubbleControllerDataset + DATA, + IBubbleControllerDatasetOptions >; -export type IPieControllerConfiguration = IChartConfiguration< +export type IPieControllerDataset = IChartDatasetBase< 'pie', - T, - L, - IPieControllerDataset, - IPieControllerChartOptions + DATA, + IPieControllerDatasetOptions >; -export type IDoughnutControllerConfiguration = IChartConfiguration< +export type IDoughnutControllerDataset = IChartDatasetBase< 'doughnut', - T, - L, - IDoughnutControllerDataset, - IDoughnutControllerChartOptions + DATA, + IDoughnutControllerDatasetOptions >; -export type IPolarAreaControllerConfiguration = IChartConfiguration< +export type IPolarAreaControllerDataset = IChartDatasetBase< 'polarArea', - T, - L, - IPolarAreaControllerDataset, - IPolarAreaControllerChartOptions + DATA, + IPolarAreaControllerDatasetOptions >; -export type IRadarControllerConfiguration = IChartConfiguration< +export type IRadarControllerDataset = IChartDatasetBase< 'radar', - T, - L, - IRadarControllerDataset, - IRadarControllerChartOptions + DATA, + IRadarControllerDatasetOptions >; -export type ConfigurationOptions = O extends IChartConfiguration ? O : never; -export type ConfigurationData = O extends IChartConfiguration - ? IChartData - : never; -export type ConfigurationDataset = O extends IChartConfiguration - ? DS - : never; +export interface IChartDatasetRegistry { + bar: IBarControllerDataset; + line: ILineControllerDataset; + scatter: IScatterControllerDataset; + bubble: IBubbleControllerDataset; + pie: IPieControllerDataset; + doughnut: IDoughnutControllerDataset; + polarArea: IPolarAreaControllerDataset; + radar: IRadarControllerDataset; +} + +export type IChartDataset = IChartDatasetRegistry[keyof IChartDatasetRegistry] + +export interface IChartData< + TYPE extends IChartType = IChartType, + DATA extends unknown[] = unknown[], + LABEL = string +> { + labels: LABEL[]; + // IChartDatasetProperties is repeated here in order to help the compiler to infer the generic types + datasets: (IChartDatasetProperties & IChartDatasetRegistry[TYPE])[]; +} + +export type IChartOptionsBase = DeepPartial< + ICoreChartOptions & + IParsingOptions & + ITooltipChartOptions & + ILegendChartOptions & + ITitleChartOptions & + IChartAnimationOptions & + IScaleChartOptions & + IElementChartOptions & + O +>; + +export interface IChartOptionsRegistry { + bar: IChartOptionsBase; + line: IChartOptionsBase; + scatter: IChartOptionsBase; + bubble: IChartOptionsBase<{}>; + pie: IChartOptionsBase; + doughnut: IChartOptionsBase; + polarArea: IChartOptionsBase; + radar: IChartOptionsBase; +} + +export type IChartOptions = IChartOptionsRegistry[keyof IChartOptionsRegistry] + +export interface IChartConfiguration< + TYPE extends IChartType = IChartType, + DATA extends unknown[] = unknown[], + LABEL = string +> { + type: TYPE; + data: IChartData; + options?: IChartOptionsRegistry[TYPE]; + plugins?: IPlugin[]; +}