Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argument of type 'HTMLElement' is not assignable to parameter of type 'CanvasImageSource'

I am trying to get the same image to load into all of the canvas in my HTML. I had previously written my whole webpage in javascript but now I am learning angular and typescript.

I am getting this error highlighted in Visual Studio Code:

Argument of type 'HTMLElement' is not assignable to parameter of type 'CanvasImageSource'. Type 'HTMLElement' is missing the following properties from type 'HTMLVideoElement': height, msHorizontalMirror, msIsLayoutOptimalForPlayback, msIsStereo3D, and 80 more.ts(2345)

But I get no error shown in the console. I can get the image to load on the HTML within the canvas (so it is working).

This is my ts:

import { Component, OnInit } from '@angular/core';  @Component({   selector: 'app-map',   templateUrl: './map.component.html',   styleUrls: ['./map.component.scss'] }) export class MapComponent implements OnInit {    constructor() { }    ngOnInit() {      document.querySelectorAll("canvas").forEach(c=>{       var ctx = c.getContext("2d");       var img = document.getElementById("P43");       ctx.drawImage(img,0,0,106,50); //(image, offsetx, offsety, x, y)     });   }  } 

VS Code highlights the error on this line ctx.drawImage(img,0,0,106,50); //(image, offsetx, offsety, x, y), it highlights img and displays the error.

I have tried to search this but the only solutions I have found are for when you had the ID for tag ( I don't as it is all canvas' on the page.) or if there is an input.

Any help is appreciated.

like image 366
JackU Avatar asked May 07 '19 06:05

JackU


People also ask

Is not assignable to parameter of type HTMLElement?

The "Type 'HTMLElement | null' is not assignable to type" error occurs when a possibly null value is assigned to something that expects an element. To solve the error, use a non-null assertion or a type guard to verify the value is a an element before the assignment.

Is not assignable to parameter of type string?

The error "Argument of type string | undefined is not assignable to parameter of type string" occurs when a possibly undefined value is passed to a function that expects a string . To solve the error, use a type guard to verify the value is a string before passing it to the function.

What is the difference between element and HTMLElement?

HTMLElement refers explicitly to an HTML element whereas Element may refer to an XML element. However, HTMLElement is technically a subset of Element.


2 Answers

You have to tell the compiler that the img variable is being set as an HTMLImageElement.

The ctx.drawImage method expects a :

HTMLOrSVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap; 

If your P43 is a canvas you have to do:

const img = document.getElementById("P43") as HTMLCanvasElement; 

if it's an image element:

const img = document.getElementById("P43") as HTMLImageElement; 

It would be even better to actually check that the element is in fact the right type of Element. You can do this with instanceof. The TypeScript compiler will also pick up the if statement, and inside the if statement the img variable will be a HTMLCanvasElement for the compiler, so explicit casting is no longer necessary:

const img = document.getElementById("P43");  if (img instanceof HTMLImageElement) {   ctx.drawImage(img,0,0,106,50); } else {   // wrong element! } 
like image 95
Poul Kruijt Avatar answered Sep 17 '22 13:09

Poul Kruijt


You need to tell the TS compiler the specific types of HTML elements that you are using in your component.

Here you are querying the document object and getting some element and calling some methods on those elements. Since TypeScript is unable to infer the types of these element and hence producing compiler errors, the Type need to be explicitly stated.

Try this:

import { Component, OnInit } from '@angular/core';  @Component({   selector: 'app-map',   templateUrl: './map.component.html',   styleUrls: ['./map.component.scss'] }) export class MapComponent implements OnInit {    constructor() { }    ngOnInit() {      document.querySelectorAll('canvas').forEach((c: HTMLCanvasElement) => {       const ctx =  <CanvasRenderingContext2D> c.getContext('2d');       const img = <HTMLImageElement> document.getElementById('P43');       ctx.drawImage(img, 0, 0, 106, 50);     });   } } 
like image 43
Ritesh Waghela Avatar answered Sep 20 '22 13:09

Ritesh Waghela