TypeScript Version: 3.0.0-dev.20180711
Search Terms: navigator, clipboard
Code
console.log(window.navigator.clipboard)
Expected behavior: No error.
Actual behavior:
error TS2339: Property 'clipboard' does not exist on type 'Navigator'
Playground Link: http://www.typescriptlang.org/play/#src=window.navigator.clipboard%3B
Related Issues: none found
W3C: https://www.w3.org/TR/clipboard-apis/#async-clipboard-api
MDN: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard
Probably missing because it's still a working draft and no browser supports it yet: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard#Browser_compatibility
Why add something to the standard library that is not supported?
no browser supports it yet
It's available in Chrome since 62 (behind a flag) and enabled by default since 66: https://www.chromestatus.com/feature/5861289330999296
Okay, so a single browser supports it already. But it's still an early draft.
We don't add non-standard DOM APIs until they're at least widely adopted.
It is an experimental API. By the way, readText
and writeText
are also supported in Firefox 63+.
As a workaround:
// navigator.clipboard.d.ts
// Type declarations for Clipboard API
// https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
interface Clipboard {
writeText(newClipText: string): Promise<void>;
// Add any other methods you need here.
}
interface NavigatorClipboard {
// Only available in a secure context.
readonly clipboard?: Clipboard;
}
interface Navigator extends NavigatorClipboard {}
It is an experimental API. By the way,
readText
andwriteText
are also supported in Firefox 63+.As a workaround:
// navigator.clipboard.d.ts // Type declarations for Clipboard API // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API interface Clipboard { writeText(newClipText: string): Promise<void>; // Add any other methods you need here. } interface NavigatorClipboard { // Only available in a secure context. readonly clipboard?: Clipboard; } interface Navigator extends NavigatorClipboard {}
Where should I place this file?
Hey, isn't it a good moment to go back to this issue and reopen it? I would really love to have it to avoid any workarounds. Chrome supports it from v66 now I have v71. Should be pretty stable.
How is "widely adopted" defined? It seems to me that according to http://gs.statcounter.com/ over half of all desktop browser users globally were on a Chrome version that supported this API already for months when the comment "We don't add non-standard DOM APIs until they're at least widely adopted." was made.
@RyanCavanaugh Can you give us any answer?
It is an experimental API. By the way,
readText
andwriteText
are also supported in Firefox 63+.
As a workaround:// navigator.clipboard.d.ts // Type declarations for Clipboard API // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API interface Clipboard { writeText(newClipText: string): Promise<void>; // Add any other methods you need here. } interface NavigatorClipboard { // Only available in a secure context. readonly clipboard?: Clipboard; } interface Navigator extends NavigatorClipboard {}
Where should I place this file?
I've done that inline like this:
// !! in any place or file !!
// Type declarations for Clipboard API
// https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
interface Clipboard {
writeText(newClipText: string): Promise<void>;
// Add any other methods you need here.
}
interface NavigatorClipboard extends Navigator {
// Only available in a secure context.
readonly clipboard?: Clipboard;
}
interface NavigatorExtended extends NavigatorClipboard {}
And where you need to use the clipboard you can cast the navigator to the created interface:
(navigator as NavigatorExtended).clipboard
.writeText(event.target.innerText)
.then(() => {
alert("Copied!");
});
(if the extended interface is in an external file you need to import it first!)
Perhaps not a great solution but if anyone else needs a hacky workaround, this worked for me.
type new var with any
let anyNavigator: any
assign new var to window.navigator
anyNavigator = window.navigator
use new var in place of navigator
anyNavigator.clipboard.writeText(event.target.defaultValue)
seems to work ok with "typescript": "^3.2.4"
So basically, this is fixed since this commit and should be available since 3.4?
Both Chrome and Firefox support the clipboard read
and write
methods now . Those should be added to the type definitions (which currently only contain readText
and writeText
).
@fr0 But it's still only a Working Draft
.
For me it's a shame that I can't properly play with modern (or experimental) APIs using only standard Typescript definitions, and I have to declare them myself instead.
@1valdis it's very reasonable that Typescript would not include these tools by default. Typescript is targeted to a very wide ranging audience. Giving bleeding-edge tools without warning and by default to developers who are unaware they might be bleeding edge easily leads to unknown bugs. TS is designed to prevent exactly these kinds of issues.
If you're keen to use experimental tools, then you should also be aware of how to extend your definition files to allow them, and how to support users who do not have the latest browsers.
@1valdis it's very reasonable that Typescript would not include these tools by default. Typescript is targeted to a very wide ranging audience. Giving bleeding-edge tools without warning and by default to developers who are unaware they might be bleeding edge easily leads to unknown bugs. TS is designed to prevent exactly these kinds of issues.
If you're keen to use experimental tools, then you should also be aware of how to extend your definition files to allow them, and how to support users who do not have the latest browsers.
Can anyone please share how to do this?
This should be sufficient (it will work using declaration merging). Put it in a clipboard.d.ts
file at the top level under on of your type root directories (tsconfig.json -> typeRoots)
interface ClipboardItem {
}
declare var ClipboardItem: {
prototype: ClipboardItem;
new(objects: Record<string, Blob>): ClipboardItem;
};
interface Clipboard {
read?(): Promise<Array<ClipboardItem>>;
write?(items: Array<ClipboardItem>): Promise<void>;
}
This should be sufficient (it will work using declaration merging). Put it in a
clipboard.d.ts
file at the top level under on of your type root directories (tsconfig.json -> typeRoots)interface ClipboardItem { } declare var ClipboardItem: { prototype: ClipboardItem; new(objects: Record<string, Blob>): ClipboardItem; }; interface Clipboard { read?(): Promise<Array<ClipboardItem>>; write?(items: Array<ClipboardItem>): Promise<void>; }
It should be under tsconfig.json -> types, it is a single file (in my case), so no reason to add it into a the rootTypes folders array option.
Most helpful comment
Hey, isn't it a good moment to go back to this issue and reopen it? I would really love to have it to avoid any workarounds. Chrome supports it from v66 now I have v71. Should be pretty stable.