'How to write typescript interface for Window object ethereum that has a request method being called

I am running the following function

import { ethers } from "ethers";


async function requestAccount() {
    await window.ethereum.request({ method: "eth_requestAccounts" });
  }

The issue I am having is I am using typescript and it complains with the following error

Property 'ethereum' does not exist on type 'Window & typeof globalThis'

So I was able to fix it with the following

declare global {
  interface Window{
    ethereum?:any
  }
}

However I don't think this is taking advantage of typescript properly. How would I write it so that the interface value is correct. I assume it should be an object with a method inside, but not sure how to write this in typescript.

Any help would be greatly appreciated.

Thanks



Solution 1:[1]

This is a quite old question but if you or someone else is still looking for an answer, you can use the ExternalProvider type of ethers.

interface Window {
  ethereum?: import('ethers').providers.ExternalProvider;
}

Here is the extracted version of ExternalProvider if you're not using ethers

type ExternalProvider = {
  isMetaMask?: boolean;
  isStatus?: boolean;
  host?: string;
  path?: string;
  sendAsync?: (request: { method: string, params?: Array<any> }, callback: (error: any, response: any) => void) => void
  send?: (request: { method: string, params?: Array<any> }, callback: (error: any, response: any) => void) => void
  request?: (request: { method: string, params?: Array<any> }) => Promise<any>
}

Solution 2:[2]

I resolved the Type Error temporarily by:

  • add: declare let window: any at the top level after your imports. Now your are able to call window.ethereum with the warning and Type Error off.

I think this overrides the global window object with a type any I'm sure this is not the best way to fix this, sort of a hack but fixes the Type error in the meantime. Let me know if this worked for your case.

Solution 3:[3]

npm i @metamask/providers

Install the above package:

import { MetaMaskInpageProvider } from "@metamask/providers";

declare global {
  interface Window{
    ethereum?:MetaMaskInpageProvider
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 nmurgor
Solution 3 Yilmaz