]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Strong typings for scales and datasets in options (#7791)
authoremmcbd <42184090+emmcbd@users.noreply.github.com>
Mon, 14 Sep 2020 13:57:00 +0000 (15:57 +0200)
committerGitHub <noreply@github.com>
Mon, 14 Sep 2020 13:57:00 +0000 (09:57 -0400)
docs/docs/developers/charts.md
types/controllers/index.d.ts
types/core/index.d.ts
types/interfaces.d.ts
types/scales/index.d.ts

index 360ec616e25c298843143ba9007949e3e4be57ba..dfe8939dd0a406d374927672c1634303d231f186 100644 (file)
@@ -158,25 +158,20 @@ If you want your new chart type to be statically typed, you must provide a `.d.t
 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`.
+* `IChartTypeRegistry` must contains the declarations for the new type, either by extending an existing entry in `IChartTypeRegistry` or by creating a new one.
 
 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'
+import { IChartTypeRegistry } from 'chart.js'
 
 declare module 'chart.js' {
     enum ChartTypeEnum {
         derivedBubble = 'derivedBubble'
     }
 
-    interface IChartDatasetRegistry<DATA extends unknown[]> {
-        derivedBubble: IChartDatasetRegistry<DATA>['bubble']
-    }
-
-    interface IChartOptionsRegistry {
-        derivedBubble: IChartOptionsRegistry['bubble']
+    interface IChartTypeRegistry {
+        derivedBubble: IChartTypeRegistry['bubble']
     }
 }
 ```
index 8b88906334cc4d53a81dd3b3cb66dfeb21e06825..a9189fec6cd5c12e3b88457b65aa32cf31a71020 100644 (file)
@@ -12,7 +12,6 @@ import {
   IPointPrefixedOptions,
   IRectangleOptions,
 } from '../elements';
-import { ICategoryScaleType, ILinearScaleType, IRadialLinearScaleType } from '../scales';
 
 export interface IControllerDatasetOptions {
   /**
@@ -80,10 +79,6 @@ export interface IBarControllerDatasetOptions
 }
 
 export interface IBarControllerChartOptions {
-  scales: {
-    _index_: ICategoryScaleType;
-    _value_: ILinearScaleType;
-  };
 }
 
 export interface BarController extends DatasetController {}
@@ -169,12 +164,7 @@ export interface IScatterDataPoint {
   y: number;
 }
 
-export interface IScatterControllerChartOptions extends ILineControllerChartOptions {
-  scales: {
-    x: ILinearScaleType;
-    y: ILinearScaleType;
-  };
-}
+export type IScatterControllerChartOptions = ILineControllerChartOptions;
 
 export interface ScatterController extends LineController {}
 export const ScatterController: IChartComponent & {
@@ -276,10 +266,6 @@ export interface IPolarAreaControllerChartOptions {
    */
   startAngle: number;
 
-  scales: {
-    r: IRadialLinearScaleType;
-  };
-
   animation: IPolarAreaAnimationOptions;
 }
 
index 7eff0b2541e029800033b193481d7f1b1779a4cb..a497b245a3b4e1b4ec5e095623ced5fb0ccf521a 100644 (file)
@@ -10,7 +10,15 @@ import {
   TimeUnit,
   IEvent,
 } from './interfaces';
-import { IChartDataset, IChartConfiguration, IChartType } from '../interfaces';
+import {
+  DefaultDataPoint,
+  IChartConfiguration,
+  IChartData,
+  IChartDataset,
+  IChartOptions,
+  IChartType,
+  IScaleOptions
+} from '../interfaces';
 
 export interface IDateAdapter {
   /**
@@ -232,7 +240,11 @@ export interface IParsingOptions {
     | false;
 }
 
-export declare class Chart<TYPE extends IChartType = IChartType, DATA extends unknown[] = unknown[], LABEL = string> {
+export declare class Chart<
+  TYPE extends IChartType = IChartType,
+  DATA extends unknown[] = DefaultDataPoint<TYPE>,
+  LABEL = string
+> {
   readonly platform: BasePlatform;
   readonly id: string;
   readonly canvas: HTMLCanvasElement;
@@ -248,8 +260,8 @@ export declare class Chart<TYPE extends IChartType = IChartType, DATA extends un
   readonly scale: Scale | undefined;
   readonly attached: boolean;
 
-  data: IChartConfiguration<TYPE, DATA, LABEL>['data'];
-  options: IChartConfiguration<TYPE, DATA, LABEL>['options'];
+  data: IChartData<TYPE, DATA, LABEL>;
+  options: IChartOptions<TYPE>;
 
   constructor(item: ChartItem, config: IChartConfiguration<TYPE, DATA, LABEL>);
 
@@ -858,7 +870,7 @@ export interface ITick {
   major?: boolean;
 }
 
-export interface IScaleOptions {
+export interface ICoreScaleOptions {
   /**
    * Controls the axis global visibility (visible when true, hidden when false). When display: 'auto', the axis is visible only if at least one associated dataset is visible.
    * @default true
@@ -932,7 +944,7 @@ export interface IScaleOptions {
   afterUpdate(axis: Scale): void;
 }
 
-export interface Scale<O extends IScaleOptions = IScaleOptions> extends Element<{}, O>, IChartArea {
+export interface Scale<O extends ICoreScaleOptions = ICoreScaleOptions> extends Element<{}, O>, IChartArea {
   readonly id: string;
   readonly type: string;
   readonly ctx: CanvasRenderingContext2D;
@@ -1047,7 +1059,7 @@ export interface Scale<O extends IScaleOptions = IScaleOptions> extends Element<
 }
 export const Scale: {
   prototype: Scale;
-  new <O extends IScaleOptions = IScaleOptions>(cfg: any): Scale<O>;
+  new <O extends ICoreScaleOptions = ICoreScaleOptions>(cfg: any): Scale<O>;
 };
 
 export interface IScriptAbleScaleContext {
index d7b2cf7946f266eb33c98fecc92f33ef222e065d..29a7e6bcd44d13da594766b5af3aec153edde131 100644 (file)
@@ -29,7 +29,13 @@ import {
   ITitleChartOptions,
 } from './plugins';
 import { IChartAnimationOptions, IParsingOptions, IPlugin } from './core';
-import { IScaleChartOptions } from './scales';
+import {
+  ILinearScaleOptions,
+  ILogarithmicScaleOptions,
+  ICategoryScaleOptions,
+  IRadialLinearScaleOptions,
+  ITimeScaleOptions,
+} from './scales';
 
 export type DeepPartial<T> = T extends {}
   ? {
@@ -37,6 +43,46 @@ export type DeepPartial<T> = T extends {}
     }
   : T;
 
+export type DistributiveArray<T> = T extends unknown ? T[] : never
+
+export enum ScaleTypeEnum {
+  linear = 'linear',
+  logarithmic = 'logarithmic',
+  category = 'category',
+  radialLinear = 'radialLinear',
+  time = 'time',
+  timeseries = 'timeseries',
+}
+
+export type IScaleType = keyof typeof ScaleTypeEnum;
+
+export interface ICartesianScaleTypeRegistry {
+  linear: {
+    options: ILinearScaleOptions;
+  };
+  logarithmic: {
+    options: ILogarithmicScaleOptions;
+  };
+  category: {
+    options: ICategoryScaleOptions;
+  };
+  time: {
+    options: ITimeScaleOptions;
+  };
+  timeseries: {
+    options: ITimeScaleOptions;
+  };
+}
+
+export interface IRadialScaleTypeRegistry {
+  radialLinear: {
+    options: IRadialLinearScaleOptions;
+  };
+}
+
+export interface IScaleTypeRegistry extends ICartesianScaleTypeRegistry, IRadialScaleTypeRegistry {
+}
+
 export enum ChartTypeEnum {
   bar = 'bar',
   bubble = 'bubble',
@@ -50,111 +96,119 @@ export enum ChartTypeEnum {
 
 export type IChartType = keyof typeof ChartTypeEnum;
 
-export interface IChartDatasetProperties<TYPE extends IChartType, DATA extends unknown[]> {
-  type?: TYPE;
-  data: DATA;
+export interface IChartTypeRegistry {
+  bar: {
+    chartOptions: IBarControllerChartOptions;
+    datasetOptions: IBarControllerDatasetOptions;
+    defaultDataPoint: number;
+    scales: keyof ICartesianScaleTypeRegistry;
+  };
+  line: {
+    chartOptions: ILineControllerChartOptions;
+    datasetOptions: ILineControllerDatasetOptions & IFillerControllerDatasetOptions;
+    defaultDataPoint: IScatterDataPoint;
+    scales: keyof ICartesianScaleTypeRegistry;
+  };
+  scatter: {
+    chartOptions: IScatterControllerChartOptions;
+    datasetOptions: IScatterControllerDatasetOptions;
+    defaultDataPoint: IScatterDataPoint;
+    scales: keyof ICartesianScaleTypeRegistry;
+  };
+  bubble: {
+    chartOptions: {};
+    datasetOptions: IBubbleControllerDatasetOptions;
+    defaultDataPoint: IBubbleDataPoint;
+    scales: keyof ICartesianScaleTypeRegistry;
+  };
+  pie: {
+    chartOptions: IPieControllerChartOptions;
+    datasetOptions: IPieControllerDatasetOptions;
+    defaultDataPoint: IPieDataPoint;
+    scales: keyof ICartesianScaleTypeRegistry;
+  };
+  doughnut: {
+    chartOptions: IDoughnutControllerChartOptions;
+    datasetOptions: IDoughnutControllerDatasetOptions;
+    defaultDataPoint: IDoughnutDataPoint;
+    scales: keyof ICartesianScaleTypeRegistry;
+  };
+  polarArea: {
+    chartOptions: IPolarAreaControllerChartOptions;
+    datasetOptions: IPolarAreaControllerDatasetOptions;
+    defaultDataPoint: number;
+    scales: keyof IRadialScaleTypeRegistry;
+  };
+  radar: {
+    chartOptions: IRadarControllerChartOptions;
+    datasetOptions: IRadarControllerDatasetOptions;
+    defaultDataPoint: number;
+    scales: keyof IRadialScaleTypeRegistry;
+  };
 }
 
-export type IChartDatasetBase<TYPE extends IChartType, DATA extends unknown[], O> = DeepPartial<
-  IControllerDatasetOptions & IParsingOptions & O
-> & IChartDatasetProperties<TYPE, DATA>;
-
-export type IBarControllerDataset<DATA extends unknown[] = number[]> = IChartDatasetBase<
-  'bar',
-  DATA,
-  IBarControllerDatasetOptions
->;
-export type ILineControllerDataset<DATA extends unknown[] = IScatterDataPoint[]> = IChartDatasetBase<
-  'line',
-  DATA,
-  ILineControllerDatasetOptions & IFillerControllerDatasetOptions
->;
-export type IScatterControllerDataset<DATA extends unknown[] = IScatterDataPoint[]> = IChartDatasetBase<
-  'scatter',
-  DATA,
-  IScatterControllerDatasetOptions
->;
-export type IBubbleControllerDataset<DATA extends unknown[] = IBubbleDataPoint[]> = IChartDatasetBase<
-  'bubble',
-  DATA,
-  IBubbleControllerDatasetOptions
+export type IScaleOptions<SCALES extends IScaleType = IScaleType> = DeepPartial<
+  { [key in IScaleType]: { type: key } & IScaleTypeRegistry[key]['options'] }[SCALES]
 >;
-export type IPieControllerDataset<DATA extends unknown[] = IPieDataPoint[]> = IChartDatasetBase<
-  'pie',
-  DATA,
-  IPieControllerDatasetOptions
->;
-export type IDoughnutControllerDataset<DATA extends unknown[] = IDoughnutDataPoint[]> = IChartDatasetBase<
-  'doughnut',
-  DATA,
-  IDoughnutControllerDatasetOptions
->;
-export type IPolarAreaControllerDataset<DATA extends unknown[] = number[]> = IChartDatasetBase<
-  'polarArea',
-  DATA,
-  IPolarAreaControllerDatasetOptions
+
+export type IDatasetChartOptions<TYPE extends IChartType = IChartType> = {
+  [key in TYPE]: {
+    datasets: IChartTypeRegistry[key]['datasetOptions'];
+  };
+};
+
+export type IScaleChartOptions<TYPE extends IChartType = IChartType> = {
+  scales: {
+    [key: string]: IScaleOptions<IChartTypeRegistry[TYPE]['scales']>;
+  };
+};
+
+export type IChartOptions<TYPE extends IChartType = IChartType> = DeepPartial<
+  ICoreChartOptions &
+  IParsingOptions &
+  ITooltipChartOptions &
+  ILegendChartOptions &
+  ITitleChartOptions &
+  IChartAnimationOptions &
+  IElementChartOptions &
+  IDatasetChartOptions<TYPE> &
+  IScaleChartOptions<TYPE> &
+  IChartTypeRegistry[TYPE]['chartOptions']
 >;
-export type IRadarControllerDataset<DATA extends unknown[] = number[]> = IChartDatasetBase<
-  'radar',
-  DATA,
-  IRadarControllerDatasetOptions
+
+export type DefaultDataPoint<TYPE extends IChartType> = IChartType extends TYPE ? unknown[] : DistributiveArray<
+  IChartTypeRegistry[TYPE]['defaultDataPoint']
 >;
 
-export interface IChartDatasetRegistry<DATA extends unknown[]> {
-  bar: IBarControllerDataset<DATA>;
-  line: ILineControllerDataset<DATA>;
-  scatter: IScatterControllerDataset<DATA>;
-  bubble: IBubbleControllerDataset<DATA>;
-  pie: IPieControllerDataset<DATA>;
-  doughnut: IDoughnutControllerDataset<DATA>;
-  polarArea: IPolarAreaControllerDataset<DATA>;
-  radar: IRadarControllerDataset<DATA>;
+export interface IChartDatasetProperties<TYPE extends IChartType, DATA extends unknown[]> {
+  type?: TYPE;
+  data: DATA;
 }
 
-export type IChartDataset<T extends unknown[] = unknown[]> = IChartDatasetRegistry<T>[keyof IChartDatasetRegistry<T>]
+export type IChartDataset<
+  TYPE extends IChartType = IChartType,
+  DATA extends unknown[] = DefaultDataPoint<TYPE>
+> = DeepPartial<
+  IParsingOptions &
+  { [key in IChartType]: { type: key } & IChartTypeRegistry[key]['datasetOptions'] }[TYPE]
+> & IChartDatasetProperties<TYPE, DATA>;
 
 export interface IChartData<
   TYPE extends IChartType = IChartType,
-  DATA extends unknown[] = unknown[],
+  DATA extends unknown[] = DefaultDataPoint<TYPE>,
   LABEL = string
 > {
   labels: LABEL[];
-  // IChartDatasetProperties is repeated here in order to help the compiler to infer the generic types
-  datasets: (IChartDatasetProperties<TYPE, DATA> & IChartDatasetRegistry<DATA>[TYPE])[];
+  datasets: IChartDataset<TYPE, DATA>[];
 }
 
-export type IChartOptionsBase<O> = DeepPartial<
-  ICoreChartOptions &
-    IParsingOptions &
-    ITooltipChartOptions &
-    ILegendChartOptions &
-    ITitleChartOptions &
-    IChartAnimationOptions &
-    IScaleChartOptions &
-    IElementChartOptions &
-    O
->;
-
-export interface IChartOptionsRegistry {
-  bar: IChartOptionsBase<IBarControllerChartOptions>;
-  line: IChartOptionsBase<ILineControllerChartOptions>;
-  scatter: IChartOptionsBase<IScatterControllerChartOptions>;
-  bubble: IChartOptionsBase<{}>;
-  pie: IChartOptionsBase<IPieControllerChartOptions>;
-  doughnut: IChartOptionsBase<IDoughnutControllerChartOptions>;
-  polarArea: IChartOptionsBase<IPolarAreaControllerChartOptions>;
-  radar: IChartOptionsBase<IRadarControllerChartOptions>;
-}
-
-export type IChartOptions = IChartOptionsRegistry[keyof IChartOptionsRegistry]
-
 export interface IChartConfiguration<
   TYPE extends IChartType = IChartType,
-  DATA extends unknown[] = unknown[],
+  DATA extends unknown[] = DefaultDataPoint<TYPE>,
   LABEL = string
 > {
   type: TYPE;
   data: IChartData<TYPE, DATA, LABEL>;
-  options?: IChartOptionsRegistry[TYPE];
+  options?: IChartOptions<TYPE>;
   plugins?: IPlugin[];
 }
index 729aaf457f43da0fc30dcf0cbbddaee206799c0b..68211674392bfd52f13ed815743f6db6c5389ad0 100644 (file)
@@ -1,6 +1,5 @@
-import { ScriptAbleScale, IScaleOptions, ITick, Scale } from '../core';
+import { ScriptAbleScale, ICoreScaleOptions, ITick, Scale } from '../core';
 import { Color, IChartComponent, IFontSpec, TimeUnit } from '../core/interfaces';
-import { DeepPartial } from '../interfaces';
 
 export interface IGridLineOptions {
   /**
@@ -85,7 +84,7 @@ export interface ITickOptions {
   };
 }
 
-export interface ICartesianScaleOptions extends IScaleOptions {
+export interface ICartesianScaleOptions extends ICoreScaleOptions {
   /**
    * Position of the axis.
    */
@@ -276,7 +275,7 @@ export type ITimeScaleOptions = ICartesianScaleOptions & {
      */
     round: false | TimeUnit;
     /**
-     * If boolean and true and the unit is set to 'week', then the first day of the week will be Monday. Otherwise, it will be Sunday. 
+     * If boolean and true and the unit is set to 'week', then the first day of the week will be Monday. Otherwise, it will be Sunday.
      * If `number`, the index of the first day of the week (0 - Sunday, 6 - Saturday).
      * @default false
      */
@@ -342,7 +341,7 @@ export const TimeSeriesScale: IChartComponent & {
   new <O extends ITimeScaleOptions = ITimeScaleOptions>(cfg: any): TimeSeriesScale<O>;
 };
 
-export type IRadialLinearScaleOptions = IScaleOptions & {
+export type IRadialLinearScaleOptions = ICoreScaleOptions & {
   animate: boolean;
 
   angleLines: {
@@ -476,28 +475,3 @@ export const RadialLinearScale: IChartComponent & {
   prototype: RadialLinearScale;
   new <O extends IRadialLinearScaleOptions = IRadialLinearScaleOptions>(cfg: any): RadialLinearScale<O>;
 };
-
-export interface ILinearScaleType extends DeepPartial<ILinearScaleOptions> {
-  type: 'linear';
-}
-export interface ILogarithmicScaleType extends DeepPartial<ILogarithmicScaleOptions> {
-  type: 'logarithmic';
-}
-export interface ICategoryScaleType extends DeepPartial<ICategoryScaleOptions> {
-  type: 'category';
-}
-export interface IRadialLinearScaleType extends DeepPartial<IRadialLinearScaleOptions> {
-  type: 'radialLinear';
-}
-export interface ITimeScaleType extends DeepPartial<ITimeScaleOptions> {
-  type: 'time';
-}
-export interface ITimeSeriesScaleType extends DeepPartial<ITimeScaleOptions> {
-  type: 'timeseries';
-}
-
-export interface IScaleChartOptions {
-  scales: {
-    [key: string]: { type: string } & DeepPartial<IScaleOptions>;
-  };
-}