Web3.js 扩展窗口接口类型定义

问题描述 投票:0回答:4

Web3.js web3 进入

window
对象。

MetaMask 等浏览器钱包将以太坊注入到

window
对象中。

现在在打字稿中为了减轻编译错误,我正在按如下方式进行转换

(window as any).ethereum

查看 Web3 存储库和钱包存储库(例如 MetaMask)后,发现

Window
对象没有可导入/可复制的打字稿定义/接口。

一个可能的解决方案是编写自己的界面并扩展 Window,查看 Window 对象并尝试推断类型 - 不理想

其他使用过 web3.js 和 typescript 的开发者,你们是如何克服 VS Code 中的 Window 类型界面问题和智能感知建议的?

typescript ethereum web3js
4个回答
26
投票

官方 Metamask Provider 存储库现在导出您可以/应该用于扩展 Window 接口的类型。

与 @Felipe 的答案相同,使用

MetamaskInpageProvider
而不是
Ethereumish
,将以下内容添加到项目中的 Typescript 声明文件中。

// metamask.d.ts
import { MetaMaskInpageProvider } from "@metamask/providers";

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


14
投票

我最近也遇到了这个。我无法从 DefinelyTyped 找到合适的 typings 包,因此我开始根据自己的使用情况和 Metamask 文档 进行推断,并创建了迄今为止有效的东西。

也许社区可以用自己的贡献来编辑这个答案。

为了使用

ethereum
对象而不被TS抱怨,我在window对象中声明它:

declare global {
    interface Window {
        ethereum: Ethereumish;
    }
}

临时的以太坊提供商类型,

Ethereumish
看起来像这样:

import { ProviderMessage, ProviderRpcError, ProviderConnectInfo, RequestArguments } from 'hardhat/types';

export interface EthereumEvent {
    connect: ProviderConnectInfo;
    disconnect: ProviderRpcError;
    accountsChanged: Array<string>;
    chainChanged: string;
    message: ProviderMessage
}

type EventKeys = keyof EthereumEvent;
type EventHandler<K extends EventKeys> = (event: EthereumEvent[K]) => void;

export interface Ethereumish {
    autoRefreshOnNetworkChange: boolean;
    chainId: string;
    isMetaMask?: boolean;
    isStatus?: boolean;
    networkVersion: string;
    selectedAddress: any;

    on<K extends EventKeys>(event: K, eventHandler: EventHandler<K>): void;
    enable(): Promise<any>;
    request?: (request: { method: string, params?: Array<any> }) => Promise<any>
    /**
     * @deprecated
     */
    send?: (request: { method: string, params?: Array<any> }, callback: (error: any, response: any) => void) => void
    sendAsync: (request: RequestArguments) => Promise<unknown>
}

如你所见,到目前为止我还无法弄清楚很多事情的确切类型,但重要的方法

send
sendAsync
在我的经验中是准确的。

另一个有用的模板是我在 @ethersproject/providers/src.ts/web3-provider.ts 中找到的东西

export 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>
}

这可以在加载新提供者时使用

new ethers.providers.Web3Provider(myProvider: ExternalProvider)

1
投票

我将把我目前使用的东西转储在这里。

src/{anything}.ts
例如
src/interfaces.d.ts
interface Window {
  // pick one
  ethereum: EthereumProvider
  // ethereum: ExternalProvider
  // ethereum: AbstractProvider
}

// ExternalProvider seems to be the official ethersproject type for the window.ethereum object, however, `new Web3(ethereum)` does not like it so we must improvise.
declare type ExternalProvider = import('@ethersproject/providers').ExternalProvider
declare type AbstractProvider = import('web3/node_modules/web3-core/types').AbstractProvider
interface EthereumProvider extends ExternalProvider {
  _state: {
    accounts: string[]
  }
  on(event: 'close' | 'accountsChanged' | 'chainChanged' | 'networkChanged', callback: (payload: any) => void): void
  once(event: 'close' | 'accountsChanged' | 'chainChanged' | 'networkChanged', callback: (payload: any) => void): void
  removeAllListeners(): void
  sendAsync: AbstractProvider['sendAsync']
}

此文件是一个脚本,因为它不导入和导出任何内容(与模块不同),使其声明环境 - 全局可用。只需确保它包含在 include/blob 数组中的

tsconfig.json
 文件中
"include": ["..."]

更多阅读:
https://github.com/MetaMask/providers
github.com~ethers.js @ExternalProvider


1
投票

我的朋友们,如果您将

React
TypeScript
一起使用,只需执行此操作,一切都会正常! 相信我:)

  1. 在项目的根目录中创建

    global.d.ts
    并放入此代码

     声明全局 {
         界面窗口{
             以太坊: import('ethers').providers.ExternalProvider;
         }
     }
     
  2. 然后在

    react-app-env.d.ts
    中输入这段代码

     界面窗口 {
         以太坊:任何;
     }
     

现在你有了代码片段并且没有错误!!

© www.soinside.com 2019 - 2024. All rights reserved.