Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TS: Argument of type 'HTMLElement' is not assignable to parameter of type 'ChartItem' #9427

Closed
DavideViolante opened this issue Jul 16, 2021 · 10 comments
Labels
type: support type: types Typescript type changes

Comments

@DavideViolante
Copy link

Expected Behavior

No error?

Current Behavior

Error: client/app/shared/chartFunctions.ts:32:20 - error TS2345: Argument of type 'HTMLElement' is not assignable to parameter of type 'ChartItem'.
  Type 'HTMLElement' is missing the following properties from type 'HTMLCanvasElement': height, width, getContext, toBlob, and 2 more.

32   return new Chart(chartElem, chartConfig);
       

Possible Solution

idk

Steps to Reproduce

I just upgraded from 3.3.2 to 3.4.x

Context

Angular project:

import Chart from 'chart.js/auto';

function generateBarChart(res: any): any {
  const chartElem = document.getElementById(`bar-chart`);
  const data = {
    labels: res.labels
    datasets: [{ label: `Number of items`, data: res.data }],
  };
  const chartConfig = {
    type: 'bar',
    data,
    options: {
      ...
    },
  };
  return new Chart(chartElem, chartConfig); // <--- line of error
}

Environment

  • Chart.js version: >=3.4.0
  • Browser name and version: Chrome latest
  • Link to your project:
@etimberg etimberg added the type: types Typescript type changes label Jul 16, 2021
@etimberg
Copy link
Member

etimberg commented Jul 17, 2021

I looked into this and ChartItem is defined as:

export declare type ChartItem =
  | string
  | CanvasRenderingContext2D
  | OffscreenCanvasRenderingContext2D
  | HTMLCanvasElement
  | OffscreenCanvas
  | { canvas: HTMLCanvasElement | OffscreenCanvas }
  | ArrayLike<CanvasRenderingContext2D | HTMLCanvasElement | OffscreenCanvas>;

Passing any HTMLElement is not supported by the constructor, so you will need to cast the return of getElementById to an HTMLCanvasElement

import Chart from 'chart.js/auto';

function generateBarChart(res: any): any {
  const chartElem = <HTMLCanvasElement>document.getElementById(`bar-chart`);
  const data = {
    labels: res.labels
    datasets: [{ label: `Number of items`, data: res.data }],
  };
  const chartConfig = {
    type: 'bar',
    data,
    options: {
      ...
    },
  };
  return new Chart(chartElem, chartConfig);
}

@DavideViolante
Copy link
Author

DavideViolante commented Jul 18, 2021

Ok thanks, I also had to cast the type of chartConfig as ChartConfiguration to prevent this type error:

Error: client/app/shared/chartFunctions.ts:32:31 - error TS2345: Argument of type '{ type: string; data: { labels: any; datasets: { label: string; data: any; }[]; }; options: any; }' is not assignable to parameter of type 'ChartConfiguration<keyof ChartTypeRegistry, any, unknown>'.
  Types of property 'type' are incompatible.
    Type 'string' is not assignable to type 'keyof ChartTypeRegistry'.

32   return new Chart(chartElem, chartConfig);

So the final code became:

import { ChartConfiguration } from 'chart.js';
import Chart from 'chart.js/auto';

const chartElem = document.getElementById(`bar-chart-week${idSuffix}`) as HTMLCanvasElement;
...
const chartConfig = {
  ...
} as ChartConfiguration; 
...

I would recommend to add a documentation about this somewhere for TypeScript users (and Angular users).

@etimberg
Copy link
Member

It looks like TS is having trouble inferring the type from the options. You don't need a cast though, if you declare the chartConfig as ChartConfiguration is also works

const chartConfig: ChartConfiguration = {
  type: 'bar',
  data,
  options: {},
};

@DavideViolante
Copy link
Author

If I use

const chartConfig: ChartConfiguration = {

Then the line with type: 'bar' says:

Type 'string' is not assignable to type 'keyof ChartTypeRegistry'.ts(2322)
index.esm.d.ts(3417, 3): The expected type comes from property 'type' which is declared here on type 'ChartConfiguration<keyof ChartTypeRegistry, (number | ScatterDataPoint | BubbleDataPoint)[], unknown>'

@DavideViolante
Copy link
Author

DavideViolante commented Jul 19, 2021

If I edit index.esm.d.ts at line 3299 with this, the above error goes away:

...
export interface ChartTypeRegistry {
  [bar: string]: { // line 3299, it was bar: {
    chartOptions: BarControllerChartOptions;
    ...

Inspired from: https://www.typescriptlang.org/docs/handbook/2/keyof-types.html
In this way we are saying that keyof ChartTypeRegistry is a string (see line 3357)

@etimberg
Copy link
Member

What version of typescript are you using?

@DavideViolante
Copy link
Author

DavideViolante commented Jul 19, 2021

With 4.3.2 (VS Code version) I got the error, with 4.2.4 no (package.json version).

tss

@etimberg
Copy link
Member

Ok, I tested with 4.1.x and it worked fine. There are other things broken starting in 4.2.0 (#9328 for example)

@etimberg
Copy link
Member

@DavideViolante are you able to test this again with chart.js v3.5.0? The types should work better for TS >= 4.2.0

@DavideViolante
Copy link
Author

DavideViolante commented Jul 26, 2021

It's working with the same code as before, using as ChartConfiguration and as HTMLCanvasElement.
Removing one of them or using variable: <Type> raises the same errors of before.
TS version 4.3.5

@chartjs chartjs locked and limited conversation to collaborators Jul 28, 2021
@kurkle kurkle closed this as completed Jul 28, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
type: support type: types Typescript type changes
Projects
None yet
Development

No branches or pull requests

3 participants