You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript声明window.ethereum报ts(2687)修饰符不一致问题排查

TS2687 扩展Window.ethereum类型报「所有声明必须具备相同修饰符」排查方案

报错根因

TS2687触发逻辑很明确:同一个接口的同名属性,在所有声明合并的条目里,修饰符(可选?、只读readonly等)必须完全一致。
你本地没写其他自定义声明,说明冲突的声明来自项目依赖的第三方类型包,常见来源包括:

  • @metamask/providers自身、web3/ethers/wagmi等链相关依赖的全局类型补丁
  • 新版TS内置DOM类型、@types/chrome等浏览器环境类型包
    这些依赖里已经提前声明了Window.ethereum为可选属性(即ethereum?: XxxProvider,和实际场景一致:用户没装钱包时这个属性本来就不存在),你自己写的声明把它设为必填,修饰符不匹配就会抛错。
    至于无法稳定复现,基本是依赖版本变动导致的:第三方包更新时可能新增、删除或修改了这个属性的声明,锁文件变化、重新装依赖都可能让报错出现或消失。

排查步骤

不用全局翻文件找冲突:

  1. 在IDE里把光标放到报错位置的ethereum属性上
  2. 触发「跳转到定义」(默认快捷键F12,右键菜单也能找到入口)
  3. IDE会列出所有对Window.ethereum的声明,直接就能看到冲突的声明位置、对应的修饰符是什么

解决方法

按推荐优先级排序:

  1. 对齐修饰符(最推荐,符合实际业务逻辑)
    把你自己写的声明里的ethereum改成可选属性,和已有声明保持一致,调用时用可选链做空值保护即可,示例代码:
    import { MetaMaskInpageProvider } from "@metamask/providers";
    
    declare global {
        interface Window {
            // 对齐可选修饰符,解决TS2687
            ethereum?: MetaMaskInpageProvider;
        }
    }
    
    // 调用时做空值兼容,覆盖用户未安装钱包的场景
    window.ethereum?.request({ method: "eth_requestAccounts" });
    
  2. 调用时类型断言(适合不想改全局声明的场景)
    如果不想修改全局声明,直接在调用位置做类型断言即可,不用处理声明合并冲突:
    const ethereum = window.ethereum as MetaMaskInpageProvider;
    ethereum.request({ method: "eth_requestAccounts" });
    
  3. 排除冲突类型包(适合多依赖重复声明的场景)
    如果排查到是无关依赖引入了冲突的ethereum声明,可以在tsconfig.json的compilerOptions.types字段里显式指定项目需要加载的类型包,过滤掉多余的冲突声明,注意不要遗漏项目需要的其他类型。

内容的提问来源于stack exchange,提问作者plutownium

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 06:33:29