Search code examples
chart.jsreact-chartjs

tooltip callback cannot recognize metadata (TS 2339)


I have the following toy data:

export const playData = {
  datasets: [
    {
      label: 'Dataset 1',
      showLine: true,
      data: [{ x: 1, y: 10, name: 'John' }, { x: 2, y: 5, name: 'Linda' }, { x: 3, y: 7, name: 'Erin' }, { x: 4, y: 4, name: 'Chloe' }, { x: 5, y: 8, name: 'Paul' }],
      borderColor: 'rgb(255, 99, 132)',
      backgroundColor: 'rgba(255, 99, 132, 0.5)',
    },
    
};

I am then trying to make a custom tooltip showing this data, which works as expected:

export function Chart(props: { chartData: ChartData }) {
  return <Scatter
    data={props.chartData}
    options={{
      responsive: true,
      scales: {
        x: {
          title: {
            display: true,
            text: 'Age (years)'
          },
        },
        y: {
          title: {
            display: true,
            text: 'Change in Height (inches)'
          }
        }
      },
      plugins: {
        legend: {
          position: 'top' as const,
        },
        tooltip: {
          callbacks: {
            label: (context) => {
              return [context.raw.name, `age: ${context.parsed.x} years`, `height change: ${context.parsed.y} in`]
            }
          }
        }
      },
    }}
  />;
}

But TS underlines the final context.raw.name and says

Property 'name' does not exist on type 'unknown'.ts(2339)

How can I fix this?


Solution

  • You can create your own custom interface by extending the one that is already being used and add the custom option you added to your dataset:

    import { Chart, TooltipItem  } from 'chart.js';
    
    interface CustomTooltipItem extends TooltipItem<'scatter'> {
      raw: {
        x: number,
        y: number,
        name: string,
      }
    }
    
    const ctx = document.getElementById("myChart") as HTMLCanvasElement;
    const myChart = new Chart(ctx, {
        type: 'scatter',
        data: {
          datasets: [{
            label: '# of Votes',
            data: [{ x: 1, y: 10, name: 'John' }, { x: 2, y: 5, name: 'Linda' }, { x: 3, y: 7, name: 'Erin' }, { x: 4, y: 4, name: 'Chloe' }, { x: 5, y: 8, name: 'Paul' }],
          }]
        },
        options: {
          plugins: {
            tooltip: {
              callbacks: {
                label: (context: CustomTooltipItem) => {
                  return [context.raw.name, `age: ${context.parsed.x} years`, `height change: ${context.parsed.y} in`]
                }
              }
            }
          }
        }
    });
    

    https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgYQBYENYBo4BUIQA2MwYAkjAKYhxwC+cAZlBDQOQDGGsAdAFYBnNgG4AsACgJwAHZUojdB0ooArgJit8REuSo1KADyrSAJgLwFipCtQA8bAR3Qw5bAHyIJtKOgDuALk9xWloDQOkVEAAjSigsLxCAT3DImLiE2ml0EEpA9SgZAHN44PoJOgkJDghpdTgOGAM4AF44EwgOSMpZHkLKGABRQmpumAAhRLITAAoAIhBEtEwYWYBKOHRzAAlcAFkAGWR0aQA3TaGR2TFxatr4BaXYFrhpSl8UbhhphoMcBAy4DBEmBcnAHE4XLE2CUQm1nOhAv9SrCTPCBP0BIEANpI2GwwjoGKEQJsADEcAgjDgADUIFQhDC8bRUTAEXAcXAwnAAIw4ZI8gAMOCyORJACkIKhpGx6H9OYEAEx8wIAVmF2VBbH2MlRMrocq5AGZlXAAOzq0VggYFaWyxDyuAAFhNzpeGpJaEIEEoeoNqpNAA4LZqAAroFSEPUAXUZsLoUYB+oBEDAJBqmKCTLAhBUhRkGdxTMBlh0iIBTKchEIUUUAGsC+WiwSiYFvjUqEZAsg1BoQForLpqOtmh5C0W8VB+iooNJ2bcOzAeD5fDwRZQcAADdB9QIAEgQ88Mi7AmHRJh4BgYiUop43m9QlGAhVQ8C4xx3cH3h6MPBPUDPPCJAwMgbgmyLjmU4FMhUUEhDB0GJuUqzCEAA