vue-chartjs addPlugin() を typescript で使おうとして遭遇したエラーと解決策

vue-chartjsをtypscriptで使っている際に、「chartの中にテキストを表示したい」などの理由からpluginを使うケースがあると思います。

このとき、[公式ドキュメント](https://vue-chartjs.org/api/#addplugin)や[Qiita記事](https://qiita.com/fm0707/items/944c2f22184633859637)を参考に`addPlugin()`をつかって下記のような実装をしたところ、エラーが発生しました。
Githubで解決策を見つけたのですが、公式ドキュメントには記載がないようなので共有します。

## :rocket: TL;DR

https://github.com/apertureless/vue-chartjs/pull/276

## :frowning2: Error

:pencil2: コード

```vuejs
<script lang="ts">
import { Component, Prop, Watch, Mixins } from 'vue-property-decorator';
import { Pie, mixins } from 'vue-chartjs';
import Chart from 'chart.js';

@Component({})
export default class PieChart extends Mixins(Pie, mixins.reactiveProp) {
  @Prop() public chartData!: Chart.ChartData;
  public chartOptions: Chart.ChartOptions = {
    cutoutPercentage: 50,
  };

  public mounted() {
    if (this.chartData.datasets !== undefined) {
      for (const dataset of this.chartData.datasets) {
        dataset.type = 'pie';
      }
    }
    this.addPlugin({ // ここがダメぽ
      afterDraw: (chart: any, easing: string) => {
        let dataSum = 0;
        chart.data.datasets[0].data.forEach((elem: any) => {
          dataSum += elem;
        });
        chart.data.datasets.forEach((dataset: any, i: number) => {
          const meta = chart.getDatasetMeta(i);
          if (!meta.hidden) {
            meta.data.forEach((element: any, index: number) => {
              const dataString = (Math.round(dataset.data[index] / dataSum * 1000) / 10).toString() + '%';
              const position = element.tooltipPosition();

              chart.ctx.fillStyle = 'white';
              chart.ctx.font = Chart.helpers.fontString(12, 'normal', 'Helvetica Neue');
              chart.ctx.textAlign = 'center';
              chart.ctx.textBaseline = 'middle';

              if (dataString !== '0%') {
                chart.ctx.fillText(dataString, position.x, position.y);
              }
            });
          }
        });
      },
    });
    this.renderChart(this.chartData, this.chartOptions);
  }
}
</script>
```

:thinking:エラー内容

```
Argument of type '{ afterDraw: (chart: any, easing: string) => void; }' is not assignable to parameter of type 'string[] | undefined'.
  Object literal may only specify known properties, and 'afterDraw' does not exist in type 'string[] | undefined'.
```

つまり `addPlugin()` の引数の型が違うよと。

## :relaxed: 解決策

どうやら使い方が間違っていたらしく、下記に情報がありました。
https://github.com/apertureless/vue-chartjs/issues/274
https://github.com/apertureless/vue-chartjs/pull/276

つまりこんな感じで回避できるとのこと。
issueにあるように chart コンポーネントからは `addPlugin()` を無くして、

```vuejs
<script lang="ts">
import { Component, Prop, Watch, Mixins } from 'vue-property-decorator';
import { Pie, mixins } from 'vue-chartjs';
import Chart from 'chart.js';

@Component({})
export default class PieChart extends Mixins(Pie, mixins.reactiveProp) {
  @Prop() public chartData!: Chart.ChartData;
  public chartOptions: Chart.ChartOptions = {
    cutoutPercentage: 50,
  };

  public mounted() {
    if (this.chartData.datasets !== undefined) {
      for (const dataset of this.chartData.datasets) {
        dataset.type = 'pie';
      }
    }
    this.renderChart(this.chartData, this.chartOptions);
  }
}
</script>
```

親コンポーネントで

```vuejs
<template>
  <div>
    <PieChart :chart-data="chartData" :plugins="[rateTextInChart]"></PieChart>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Watch, Vue } from 'vue-property-decorator';
import PieChart from '@/components/charts/PieChart.vue';
import Chart from 'chart.js';

@Component({
  components: {
    PieChart,
  },
})
export default class DonutsChart extends Vue {
  private chartData: Chart.ChartData = {};
  private rateTextInChart = {
    afterDraw: (chart: any, easing: string) => {
      let dataSum = 0;
      chart.data.datasets[0].data.forEach((elem: any) => {
        dataSum += elem;
      });
      chart.data.datasets.forEach((dataset: any, i: number) => {
        const meta = chart.getDatasetMeta(i);
        if (!meta.hidden) {
          meta.data.forEach((element: any, index: number) => {
            const dataString = (Math.round(dataset.data[index] / dataSum * 1000) / 10).toString() + '%';
            const position = element.tooltipPosition();

            chart.ctx.fillStyle = 'white';
            chart.ctx.font = Chart.helpers.fontString(12, 'normal', 'Helvetica Neue');
            chart.ctx.textAlign = 'center';
            chart.ctx.textBaseline = 'middle';

            if (dataString !== '0%') {
              chart.ctx.fillText(dataString, position.x, position.y);
            }
          });
        }
      });
    },
  };
// 略
}
</script>
```

として `plugins` のプロパティにプラグイン設定を渡してあげればいいようです。

 

誰かの役に立ちますように:innocent:
おしまい。