Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chart.js Types of property 'type' are incompatible. Type 'string' is not assignable to type '"line" | "bar" | "scatter"

client:159 src/app/analytics-page/analytics-page.component.ts:211:26 - error TS2345: Argument of type '{ type: string; options: { responsive: boolean; }; data: { labels: string[]; datasets: { label: string; data: number[]; borderColor: string; steppedLine: boolean; fill: boolean; }[]; }; }' is not assignable to parameter of type 'ChartConfiguration<"line" | "bar" | "scatter" | "bubble" | "pie" | "doughnut" | "polarArea" | "radar", number[], string>'.
  Types of property 'type' are incompatible.
    Type 'string' is not assignable to type '"line" | "bar" | "scatter" | "bubble" | "pie" | "doughnut" | "polarArea" | "radar"'.

211       new Chart(gainCtx, createChartConfig(gainConfig))
import {AfterViewInit, Component, ElementRef, OnDestroy, ViewChild} from '@angular/core'
import {AnalyticsService} from '../shared/services/analytics.service'
import {AnalyticsPage, ChartConfig} from '../shared/interfaces'
import {Chart} from 'chart.js'
import {Subscription} from 'rxjs'

@Component({
  selector: 'app-analytics-page',
  templateUrl: './analytics-page.component.html',
  styleUrls: ['./analytics-page.component.scss']
})
export class AnalyticsPageComponent implements AfterViewInit, OnDestroy {

  @ViewChild('gain') gainRef!: ElementRef
  @ViewChild('order') orderRef!: ElementRef

  aSub!: Subscription
  average!: number
  pending = true

  constructor(private service: AnalyticsService) {
  }

  ngAfterViewInit() {
    const gainConfig: any = {
      label: 'Выручка',
      color: 'rgb(255, 99, 132)'
    }

    const orderConfig: any = {
      label: 'Заказы',
      color: 'rgb(54, 162, 235)'
    }

    this.aSub = this.service.getAnalytics().subscribe((data: AnalyticsPage) => {
      this.average = data.average

      gainConfig.labels = data.chart.map(item => item.label)
      gainConfig.data = data.chart.map(item => item.gain)

      orderConfig.labels = data.chart.map(item => item.label)
      orderConfig.data = data.chart.map(item => item.order)

      // **** Gain ****
      // gainConfig.labels.push('08.05.2018')
      // gainConfig.labels.push('09.05.2018')
      // gainConfig.data.push(1500)
      // gainConfig.data.push(700)
      // **** /Gain ****

      // **** Order ****
      // orderConfig.labels.push('08.05.2018')
      // orderConfig.labels.push('09.05.2018')
      // orderConfig.data.push(8)
      // orderConfig.data.push(2)
      // **** /Order ****

      const gainCtx = this.gainRef.nativeElement.getContext('2d')
      const orderCtx = this.orderRef.nativeElement.getContext('2d')
      gainCtx.canvas.height = '300px'
      orderCtx.canvas.height = '300px'

      new Chart(gainCtx, createChartConfig(gainConfig))
      new Chart(orderCtx, createChartConfig(orderConfig))

      this.pending = false
    })
  }

  ngOnDestroy() {
    if (this.aSub) {
      this.aSub.unsubscribe()
    }
  }

}


function createChartConfig({labels, data, label, color}: ChartConfig) {
  return {
    type: 'line',
    options: {
      responsive: true
    },
    data: {
      labels,
      datasets: [
        {
          label, data,
          borderColor: color,
          steppedLine: false,
          fill: false
        }
      ]
    }
  }
}

The problem is in type: 'line',. Chart.js is not working, it not work with any type, throws error.

like image 779
Tatyana Molchanova Avatar asked Apr 12 '21 12:04

Tatyana Molchanova


Video Answer


1 Answers

Looks like your TypeScript compiler is complaining because the chart type property is a specific type rather than a string.

Option 1:

Import ChartType and cast type as ChartType.

import {  Chart, ChartType, ...} from 'chart.js';

 ...

function createChartConfig({labels, data, label, color}: ChartConfig) {
  return {
    type: 'line' as ChartType,
    options: {
   ...

Option 2: (The easier/hacky way)

Cast the entire config as any.

new Chart(gainCtx, createChartConfig(gainConfig) as any);

In any case, you will need to import and register the needed controllers, elements, scales, etc. Registering registerables registers everything, but it is better to register only what you require for your specific chart. See the Integration instructions for more information.

import { Chart, registerables } from 'chart.js';
...
Chart.register(...registerables);
like image 191
James Lawruk Avatar answered Oct 09 '22 19:10

James Lawruk