0

[Cross-posted to https://github.com/chartjs/Chart.js/discussions/10864].

I'm using Chart.js with React and TypeScript. Following this answer, I've typed my custom plugin options in an index.d.ts-file, like so:

export type MyPluginOptions = {
    foo: string;
    bar: string;
  };

declare module 'chart.js' {
  interface PluginOptionsByType<TType extends ChartType> {
    myPlugin?: MyPluginOptions;
  }
}

The problem is that Chart.js has this wrapped (I think) in a _DeepPartialObject<>, which means that foo and bar become optional against my intention. Can I somehow counteract this, or how should I deal with it? I would like all keys to be required. I feel like I should be able to utilize TypeScipt's Required<> somehow, but I can't seem to figure out how.


For more context, I then have something like this defined:

const myChartOptions: ChartOptions<'bar'> = {
  // other options,
  plugins: {
    myPlugin: {
      foo: 'something',
      bar: 'something else',
    },
  },
};

Here TypeScript is fine with foo and/or bar missing. Then, when defining the action of the plugin, one thing I've tried looks something like:

const myPlugin : Plugin<'bar'> = {
  id: 'my-plugin',
  afterDraw: function (chart, _args, options: MyPluginOptions) {
    if (options) {
      const x = options.foo;
      const y = options.bar;
      // more code
  };
};

Since I "cheated" by writing options: MyPluginOptions, TypeScript infers that foo and bar exist. But it also infers that options exists, which it could not, so that's can be a problem. Alternatively, I could have

const myPlugin : Plugin<'bar'> = {
  id: 'my-plugin',
  afterDraw: function (chart) {
    const options = chart.plugins?.myPlugin as MyPluginOptions;
    if (options) {
      const x = options.foo;
      const y = options.bar;
      // more code
  };
};

This mostly gives me what I want, but doesn't provide non-partial type checking when setting the options.


Other workarounds I can image include:

  • Setting the options in an unrelated object to circumvent the Chart.js typing entirely.
  • Actually treating them as optional keys and define default behavior on undefined keys. (Seems unnecessary in my use case, but I suspect this is the intention of the Chart.js team?).

I would love to get some more insight, especially if I'm missing the mark on the preferred way to do things.

Malte
  • 101
  • 3

0 Answers0