TypeScript报错求助:Operator '-'无法应用于bigint与number类型
解决TypeScript报错:Operator '-' cannot be applied to types 'bigint' and 'number'
问题原因
Web3.js的getBlockNumber()方法返回的是bigint类型,而你代码中的this.asyncHeight是number类型。TypeScript不允许bigint和number直接进行算术运算(加减乘除),所以currentBlockNumber - 2会触发类型错误,同时startBlock + 99 > currentBlockNumber也存在number与bigint混合比较的隐患。
解决方案(两种可选)
方案1:统一使用bigint类型(更严谨,适配Web3的返回类型)
将所有参与运算的number值转为bigint,保持类型一致:
修改代码中的关键行:
async startBlockEvent() { let success = true schedule.scheduleJob("*/10 * * * * *", async () => { try { const provieder = new Web3(Config[this.chainId].prc) // 保持currentBlockNumber为bigint类型 let currentBlockNumber = await provieder.eth.getBlockNumber() // 将this.asyncHeight转为bigint后再运算 if (currentBlockNumber > BigInt(this.asyncHeight) + 3n && success) { success = false // 转为bigint计算startBlock let startBlock = BigInt(this.asyncHeight) + 1n // 所有数字字面量用bigint(加n后缀) let endBlock = startBlock + 99n > currentBlockNumber ? currentBlockNumber - 2n : startBlock + 99n try { // 若batchGetBlock期望number参数,需转成Number(startBlock)、Number(endBlock) let result = await this.blockTx.batchGetBlock(Number(startBlock), Number(endBlock), provieder) let deployCollection = await this.insertCollection(result.collections) let updateCollection = await this.updateCollection(result.updateCollections) let updateHolder = await this.updateHolder(result.holders) let insertTransfer = await this.insertTransfer(result.orders) let updateDeposit = await this.updateDepositEvent(result.depositEvents) let insertBlockHash = await this.insertBlockHash(result.blockHashs) if (deployCollection && updateCollection && updateHolder && insertTransfer && updateDeposit && insertBlockHash) { // 若this.asyncHeight定义为number类型,转成Number(endBlock)赋值 this.asyncHeight = Number(endBlock) let updateConfig = this.sqlConfig ? this.sqlConfig : { chainId: this.chainId, asyncHeight: 0 } updateConfig.asyncHeight = Number(endBlock) this.sqlConfig = updateConfig await this.Db.update("config", updateConfig) console.log(`sync ${endBlock},deploy ${result.collections.length},mint ${result.mints.length} ,update collection ${result.updateCollections.length},wallet ${result.holders.length},request time ${result.requestTime} ms,handler data time ${result.handleDataTime} ms,validate block ${result.blockHashs.length}`) } success = true } catch (error) { console.log(error) success = true } } } catch (error) { success = true } }) }
方案2:将bigint转为number(简单直接,适合区块号不超过2^53的场景)
以太坊当前区块号远小于JS number的最大值(2^53),可以安全转换:
修改getBlockNumber的结果处理:
// 将返回的bigint转为number let currentBlockNumber = Number(await provieder.eth.getBlockNumber())
之后原代码的运算逻辑无需修改,所有变量都为number类型,类型错误会自动消失。
注意事项
- 如果项目中Web3方法返回的bigint较多,推荐用方案1,避免后续频繁类型转换
- 若
batchGetBlock方法要求参数为number类型,方案1中需要将bigint转为number传入
内容的提问来源于stack exchange,提问作者Atif Shah
相关产品推荐
相关产品推荐

