pradeep
pradeep

Reputation: 410

Property 'share' does not exist on type 'Navigator'

I need to use WebShareAPI in my Ionic application.

Here is my code as suggested in Introducing the Web Share API

if (window.navigator && window.navigator.share) {
  window.navigator.share({
    title: 'title',
    text: 'description',
    url: 'https://soch.in//',
  })
    .then(() => console.log('Successful share'))
    .catch((error) => console.log('Error sharing', error));
} else {
  alert('share not supported');
}

However, Typescript compilation fails with the following error:

[11:31:11]  typescript: src/pages/channel_home/channel_home.ts, line: 89
            Property 'share' does not exist on type 'Navigator'.

There is a likely reason explained here DOM lib: add support for navigator.share

However, I would like to know some workaround to make WebShareApi work in my Ionic app in particular, and in any Angular or Typescript app in general.

Upvotes: 31

Views: 33511

Answers (9)

edkeveked
edkeveked

Reputation: 18381

Based on this answer, you can try to define a variable of type any and assign to it your value of Type Navigator. The issue is related to TypeScript typings.

const newVariable: any = window.navigator;

if (newVariable?.share) {
  newVariable.share({
    title: 'title',
    text: 'description',
    url: 'https://soch.in//',
  })
    .then(() => console.log('Successful share'))
    .catch((error) => console.log('Error sharing', error));
} else {
  alert('Share is not supported');
}

Another option would be to extend the interface Navigator as it is suggested in the link I posted above.

Upvotes: 37

Anton Nikitsiuk
Anton Nikitsiuk

Reputation: 77

Don't use navigator.share/caches/serial and many more directly, this will lead you to an error on the HTTP connection. Verify it exists before the direct call to the property.

if ('share' in navigator) {
//Do stuff
} else {
 alert('Share API not supported');
}

Upvotes: 1

phoenisx
phoenisx

Reputation: 1689

[Update 2020]

This is fixed in Typescript's latest versions (I am not exactly sure which one, but I guess since v4.3-beta version). Check this thread for details - https://github.com/microsoft/TypeScript/issues/18642

Also, The example shared below, once updated to the latest version will not work, as it conflicts with Typescript's own typings. Thus, do not apply those changes or keep the type similar to the parent:

// global.d.ts
interface Navigator extends Navigator {
  share: (options?: ShareData) => Promise<void>;
}

share property has been removed from being optional, as per the specs, details implemented in Firefox, changes in Firefox


We can do this the Typescript way:

Firstly we need to define custom typings for our project. So, we need to define a /typings or /@types folder in your root directory.

.
└── typings

Once that is done, you need to update your tsconfig.json file to point the new custom typings folder to this one.

{
  "compilerOptions": {
    ...
    "typeRoots": [
      "./node_modules/@types",
      "./typings"
    ]
  },
  "include": [
    ...
    "typings",
    "**/*.ts",
    "**/*.tsx"
  ]
  ...
}

This will allow Typescript to look for custom types in /typings folder.

References for above:

Once the above is done, we need to create a Global .d.ts file that Typescript will look into for detecting custom types. So, in your /typings folder create a new file named global.d.ts.

// global.d.ts
interface Navigator extends Navigator {
  share?: (options: any) => Promise<void>;
}

What we are doing, is overriding the default Navigator with some extra properties to support.

Once you declare the above interface, Typescript will allow you to use navigator.share, but you need to put it inside a conditional block, as share is optional property, it might or might not be present in a Browser.

Hope this helps!!

Upvotes: 8

Matt
Matt

Reputation: 35271

Declare navigator as any

(window.navigator as any).share

Upvotes: 13

user1211030
user1211030

Reputation: 3070

If you keep getting the error, despite following the advices on this site, make sure that your page is server via https. The share functionality is not available on plain http. The following snipped worked for me.

const nav: any = window.navigator;
nav.share({ title: "Shared via my https page", url: "relativeLink" })

Upvotes: 0

Cristian Sepulveda
Cristian Sepulveda

Reputation: 1730

in my case: in Angular, on a module I use:

navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;

and typescript show the error MozGetUserMedia is not a property.

I fixed using:

declare const navigator: any; 

Maybe the same approach will works for you:

Upvotes: 3

DASPRiD
DASPRiD

Reputation: 1683

For anyone looking for a proper answer, just add this to your global.d.ts file:

type ShareData = {
    title? : string;
    text? : string;
    url? : string;
};

interface Navigator
{
    share? : (data? : ShareData) => Promise<void>;
}

This properly reflects the level 1 API.

Upvotes: 14

Avinash
Avinash

Reputation: 1243

This also works and we don't need to create a newVariable.

if (window.navigator && window.navigator.share) {
  window.navigator['share']({
    title: 'title',
    text: 'description',
    url: 'https://soch.in//',
  })
    .then(() => console.log('Successful share'))
    .catch((error) => console.log('Error sharing', error));
} else {
  alert('share not supported');
}

Upvotes: 5

Genio Rosario
Genio Rosario

Reputation: 31

This worked for me

let newVariable = (window.navigator as any)
if(newVariable.share){
  newVariable.share({
  title: 'title',
  text: 'description',
  url: 'https://soch.in//',
})
  .then(() => console.log('Successful share'))
  .catch((error) => console.log('Error sharing', error));
} else {
  alert('share not supported');
}   

Upvotes: 3

Related Questions