How to fix the "Cannot find name 'ClipboardItem'" error?

5.9k views Asked by At

Getting the error

error TS2304: Cannot find name 'ClipboardItem'

when trying to create a ClipboardItem for navigator.clipboard.write().

const clipboardItemInput = new ClipboardItem({'image/png' : blobInput});
 await navigator.clipboard.write([clipboardItemInput]);

I am using Angular 6. Do I need to add any dependencies, or is there any other method?

3

There are 3 answers

0
Oleg Valter is with Ukraine On

For TypeScript 4.4 and higher

TypeScript 4.4 updated the standard definitions library with missing interfaces and methods (full list of changes), so everything should work out-of-the-box. The following sample code now compiles without additional interfaces/declaration merges:

declare const image: ClipboardItemData;
(async () => {
  const item = new ClipboardItem({ "image/png": image });

  const files = await navigator.clipboard.read();
  if( files.length ) return;

  await navigator.clipboard.write([item]);
})();

Playground


For TypeScript 4.3 and lower

As of 2021, the TypeScript standard library is still missing a definition for the Clipboard API (and that is the reason for the "Cannot find name 'ClipboardItem'" error). There is an open issue on the source repository and a pull request on the DOM lib generator repository (because the standard library is autogenerated) that should address the issue.

In the meantime, you can add the following definitions matching how the standard library defines other global interfaces (do not forget to add a triple-slash directive /// <reference types="../../index" /> at the top of the importing file):

interface ClipboardItem {
  readonly types: string[];
  readonly presentationStyle: "unspecified" | "inline" | "attachment";
  getType(): Promise<Blob>;
}

interface ClipboardItemData {
  [mimeType: string]: Blob | string | Promise<Blob | string>;
}

declare var ClipboardItem: {
  prototype: ClipboardItem;
  new (itemData: ClipboardItemData): ClipboardItem;
};

Note that the ClipboardItemData is defined to take either Blob, string, or a promise that returns one of the former and not just a Blob (see the MDN reference, for example). It also does not hurt to augment the Clipboard interface with missing read and write methods:

interface Clipboard {
  read(): Promise<DataTransfer>;
  write(data: ClipboardItem[]): Promise<void>;
}

Finally, let's test that the definitions work as expected:

declare const image: Blob;
(async () => {
  const item = new ClipboardItem({ ["image/png"]: image });

  const { files } = await navigator.clipboard.read();
  if( files.length ) return;

  await navigator.clipboard.write([item]);
})();

Playground

0
WetABQ On

simple but not great

let anyNavigator: any;
anyNavigator = window.navigator;
const clipboardItemInput = new ClipboardItem({'image/png' : blobInput});
await anyNavigator.clipboard.write([clipboardItemInput]);

If you want to read clipboard or call any function that has a return value:

let anyNavigator: any;
anyNavigator = window.navigator;
(anyNavigator.clipboard.readText() as Promise<string>).then(data => {
// ...
});

0
Nikita On

The Typescript version might not incorporate all the features. This is where we need to extend it by creating typings or extending the existing ones. To solve the issue, try to create a types.d.ts file (reference1) and put the following in it:

declare class ClipboardItem {
  constructor(data: { [mimeType: string]: Blob });
}

Then reference the file in your component code with:

/// <reference path="types.d.ts" />

Then feel free to use the Class.

const item = new ClipboardItem({ "image/png": blob });
window.navigator['clipboard'].write([item]);

Inspiration: reference2