Home > other >  Type undefined is not assignable to type
Type undefined is not assignable to type

Time:11-03

Here, I am trying to implement pie chart (donut series) in angular. These are my html, css and ts files. I am following this resource. https://apexcharts.com/angular-chart-demos/pie-charts/simple-donut/

Link to CodeSandBox - https://codesandbox.io/s/apx-donut-simple-8fnji?from-embed

import { Component, OnInit, ViewChild } from '@angular/core';
import { ChartComponent } from "ng-apexcharts";

import {
  ApexNonAxisChartSeries,
  ApexResponsive,
  ApexChart
} from "ng-apexcharts";

export type ChartOptions = {
  series: ApexNonAxisChartSeries;
  chart: ApexChart;
  responsive: ApexResponsive[];
  labels: any;
};

@Component({
  selector: 'app-second-page',
  templateUrl: './second-page.component.html',
  styleUrls: ['./second-page.component.css']
})
export class SecondPageComponent implements OnInit {
  @ViewChild("chart") chart: ChartComponent;
  public chartOptions: Partial<ChartOptions>;

  constructor() {
    this.chartOptions = {
      series: [44, 55, 13, 43, 22],
      chart: {
        type: "donut"
      },
      labels: ["Team A", "Team B", "Team C", "Team D", "Team E"],
      responsive: [
        {
          breakpoint: 480,
          options: {
            chart: {
              width: 200
            },
            legend: {
              position: "bottom"
            }
          }
        }
      ]
    };
  }

  ngOnInit(): void {
  }

}
  #chart {
    max-width: 380px;
    margin: 35px auto;
    padding: 0;
  }
  <div id="chart">
    <apx-chart
      [series]="chartOptions.series"
      [chart]="chartOptions.chart"
      [labels]="chartOptions.labels"
      [responsive]="chartOptions.responsive"
    ></apx-chart>
  </div>

I am facing the undefined issue, but its working for them in the tutorial. Somebody please help me on this.

Error: src/app/second-page/second-page.component.html:32:8 - error TS2322: Type 'ApexNonAxisChartSeries | undefined' is not assignable to type 'ApexAxisChartSeries | ApexNonAxisChartSeries'.
  Type 'undefined' is not assignable to type 'ApexAxisChartSeries | ApexNonAxisChartSeries'.

32       [series]="chartOptions.series"
          ~~~~~~

  src/app/second-page/second-page.component.ts:19:16
    19   templateUrl: './second-page.component.html',
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component SecondPageComponent.


Error: src/app/second-page/second-page.component.html:33:8 - error TS2322: Type 'ApexChart | undefined' is not assignable to type 'ApexChart'.
  Type 'undefined' is not assignable to type 'ApexChart'.

33       [chart]="chartOptions.chart"
          ~~~~~

  src/app/second-page/second-page.component.ts:19:16
    19   templateUrl: './second-page.component.html',
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component SecondPageComponent.


Error: src/app/second-page/second-page.component.html:35:8 - error TS2322: Type 'ApexResponsive[] | undefined' is not assignable to type 'ApexResponsive[]'.
  Type 'undefined' is not assignable to type 'ApexResponsive[]'.

35       [responsive]="chartOptions.responsive"
          ~~~~~~~~~~

  src/app/second-page/second-page.component.ts:19:16
    19   templateUrl: './second-page.component.html',
                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component SecondPageComponent.


Error: src/app/second-page/second-page.component.ts:23:23 - error TS2564: Property 'chart' has no initializer and is not definitely assigned in the constructor.

23   @ViewChild("chart") chart: ChartComponent;
                         ~~~~~

✖ Failed to compile.

CodePudding user response:

I'm not entirely sure about the specifics of the library, but I can explain what the compiler is complaining about.

Whenever you use Partial in TypeScript, this can be seen as making all keys in the subject interface optional, for example

interface SomeInterface {
  key1: string;
  key2: number;
}

type PartialSomeInterface = Partial<SomeInterface>

// which is equivalent to
interface PartialSomeInterface {
  key1?: string;
  key2?: number;
}

// which is equivalent to
interface PartialSomeInterface {
  key1: string | undefined;
  key2: number | undefined;
}

Effectively, by declaring chartOptions as Partial<ChartOptions> you are saying that the object being stored may have as little as 0 keys, i.e. all of them may be missing or undefined, and that is an acceptable value for chartOptions.

When a property on this chartOptions is then passed to the <apx-chart> component, the chart component needs to have | undefined in the type definition for the property being passed in. For example, looking at the series input:

// Component definition needed
@Input() series?: ApexAxisChartSeries | ApexNonAxisChartSeries

or

@Input() series: ApexAxisChartSeries | ApexNonAxisChartSeries | undefined

The compiler is complaining that this is not the case, and a value of undefined is not acceptable. Which most likely means that the component definition is in fact:

@Input() series: ApexAxisChartSeries | ApexNonAxisChartSeries

In short Partial<ChartOptions> does not appear to be an acceptable type for chartOptions based on the demands of the child component <apx-chart>.

This is confusing, as you have quite rightly followed the documentation/example provided.

Couple of things to try/investigate:

  • As you are fortunate enough to have defined all of the properties of the ChartOptions interface in your chartOptions variable initial values, simply remove the Partial. This will tell the underlying component that every property in chartOptions is expected to be defined, and therefore all 4 keys can be passed into the component as you have done
  • If you still need to use Partial, i.e. you intend to not define all starting properties of chartOptions, is there a chance that the version of apx-chart you are using is outdated/does not match the version used in the demos?

CodePudding user response:

See the last error, it shows you the problem:

error TS2564: Property 'chart' has no initializer and is not definitely assigned in the constructor.

It's related to the typescript flag --strictPropertyInitialization introduced in version 2.7.

If --strictPropertyInitialization is enabled, the compiler checks if all properties of the component are initialized. info

There are several ways to fix that. For example, disable --strictPropertyInitialization flag in typescript compiler options in tsconfig.json file.

"compilerOptions": {
...
  "strictPropertyInitialization":false
...
}
  • Related