10

I have weird situation with canvas element and method captureStream. According to documentation HTMLCanvasElement has a method captureStream. However my Angular6 app claims that there isn't such method.

So this code won't work:

let canvas: HTMLCanvasElement;
canvas = document.createElement('canvas');
let stream = canvas.captureStream(20);

It fails on third line.

This code runs without any error:

   let canvas: any;
   canvas = document.createElement('canvas');
   let stream = canvas.captureStream(20);

How this is possible? I'm 100% sure that HTMLCanvasElement has this method and the document.createElement('canvas') returns HTMLCanvasElement.

Maciej Wojcik
  • 2,115
  • 2
  • 28
  • 47

3 Answers3

8

You can extend an exiting interface in TypeScript and cast your Element to the custom interface.

Example:

interface CanvasElement extends HTMLCanvasElement {
  captureStream(frameRate?: number): MediaStream;
}

const myCanvas = <CanvasElement> document.createElement('canvas');
const myStream = myCanvas.captureStream();
hthetiot
  • 359
  • 4
  • 8
  • 1
    better yet: `interface CanvasElement extends HTMLCanvasElement { captureStream(int): MediaStream; }`then getTracks from the returned object – user3325025 Aug 17 '20 at 21:02
  • 3
    Better yet, convert all of your TS files to JS files and go back to happy carefree days of ESLint only and no "lost man hours thanks to TypeScript compile problems". – SacWebDeveloper Oct 12 '20 at 06:05
7

According to MDN, it looks like the captureStream method is still a working draft (as of June 2021), eventhough it is not implemented by all major browsers. That is probably why it is not yet part of the type definition for HTMLCanvasElement.

Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
5th
  • 210
  • 1
  • 6
7

Available in your entire project without creating a new interface:

declare global {
   interface HTMLCanvasElement {
     captureStream(frameRate?: number): MediaStream;
  }
}
Dachstein
  • 3,994
  • 6
  • 34
  • 61
  • Just a further explanation - a given example is possible by using a TypeScript feature called declaration merging that basically merges the existing interface declaration with the one given somewhere else in the project. More information is available here: https://www.typescriptlang.org/docs/handbook/declaration-merging.html – Piotr Chojnacki Jun 27 '22 at 11:52