Ethers.js: Object literal may only specify known properties, and '"internalType"' does not exist in type 'ParamType'.

Created on 12 Feb 2020  Â·  18Comments  Â·  Source: ethers-io/ethers.js

This is a typescript compile issue, so should be able to fix this by just JSON.stringifying it and then passing it along. Making an issue here since ParamType should be able to hanlde internalType

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"prevBlockHash","type":"bytes32"},{"components":[{"internalType":"address","name":"originator","type":"address"},{"internalType":"address","name":"quotToken","type":"address"},{"internalType":"address","name":"variToken","type":"address"},{"internalType":"uint256","name":"priceNumer","type":"uint256"},{"internalType":"uint256","name":"priceDenom","type":"uint256"},{"internalType":"uint256","name":"tokenLimit","type":"uint256"},{"internalType":"uint8","name":"signatureV","type":"uint8"},{"internalType":"bytes32","name":"signatureR","type":"bytes32"},{"internalType":"bytes32","name":"signatureS","type":"bytes32"}],"internalType":"struct Engine.Order[]","name":"buyyOrders","type":"tuple[]"},{"components":[{"internalType":"address","name":"originator","type":"address"},{"internalType":"address","name":"quotToken","type":"address"},{"internalType":"address","name":"variToken","type":"address"},{"internalType":"uint256","name":"priceNumer","type":"uint256"},{"internalType":"uint256","name":"priceDenom","type":"uint256"},{"internalType":"uint256","name":"tokenLimit","type":"uint256"},{"internalType":"uint8","name":"signatureV","type":"uint8"},{"internalType":"bytes32","name":"signatureR","type":"bytes32"},{"internalType":"bytes32","name":"signatureS","type":"bytes32"}],"internalType":"struct Engine.Order[]","name":"sellOrders","type":"tuple[]"},{"components":[{"internalType":"uint16","name":"buyyOrderIndex","type":"uint16"},{"internalType":"uint16","name":"sellOrderIndex","type":"uint16"},{"internalType":"uint256","name":"quotTokenTrans","type":"uint256"},{"internalType":"uint256","name":"variTokenTrans","type":"uint256"},{"internalType":"uint256","name":"quotTokenArbit","type":"uint256"}],"internalType":"struct Engine.Exchange[]","name":"exchanges","type":"tuple[]"}],"name":"execute","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"executorOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_executorOracle","type":"address"}],"name":"setExecutorOracle","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]

enhancement fixed

Most helpful comment

Sorry, I’ve been busy with the EIP-1559 changes.

I will look into this (and a few other issues) early this week. I suspect it will be an easy change, I mainly am interested in why this changed; it used to be TS didn’t care about extra properties, only missing ones.

I wonder if they changed how types vs. interfaces work regarding object literals. I just need to look into it to find the best solution; ideally solidity adding new keys shouldn’t break JsonFragments. :)

All 18 comments

What is internalType? Is this in v4 or v5?

In v5, does this not match JsonFragment?

I get confused by how TypeScript sometimes chooses to allow additional properties and other times, not... does this need to extend any or { [ key: string ]: any } maybe?

I'm actually not sure what internalType is. Not sure what you mean by v4 vs v5. Is there a versioned spec for solc ABIs?

does this need to extend any or { [ key: string ]: any } maybe

Yup, that would work. But its for JsonFragmentType, not JsonFragment.

Oh, I mean what version of ethers are you using? The v4 branch (current master) or v5 (@ next).

4.0.42

Can you try upgrading the 4.0.44 and see if you still have the problem? (There were some typing issues introduced that were fixed after 4.0.43; it may or may not help, just checking)

Oh, can you also include a code snippet of what you are trying to do that causes that error?

@aakilfernandes Did you try out 4.0.44 and still have the same problem?

I think this has been addressed? If not, please reopen.

Thanks! :)

Typescript is still unhappy about this in v5.2.0, have to JSON.stringify() it to appease the compiler. The change happened here: https://github.com/ethereum/solidity/releases/tag/v0.5.11.

Adding it to fragments might solve the issue.

Happy to drop a PR if you agree.

Can you include the error?

Type '{ indexed: false; internalType: string; name: string; type: string; }' is not assignable to type 'JsonFragmentType'.
  Object literal may only specify known properties, and 'internalType' does not exist in type 'JsonFragmentType'.

interestingly, the error is thrown with this:

import { ContractInterface } from 'ethers';

export const CONTRACT_ABI: ContractInterface = [
  {
    anonymous: false,
    inputs: [
      {
        indexed: false,
        internalType: 'address',
        name: 'previousAdmin',
        type: 'address',
      },
  .....
];

but not this:

import { ContractInterface } from 'ethers';

const CONTRACT_ABI_RAW = [
  {
    anonymous: false,
    inputs: [
      {
        indexed: false,
        internalType: 'address',
        name: 'previousAdmin',
        type: 'address',
      },
  .....
];

export const CONTRACT_ABI: ContractInterface = CONTRACT_ABI_RAW;

I can confirm the problem exists. internalType is not listed in JsonFragmentType.

@ricmoo any objections to me opening a PR to address?

Sorry, I’ve been busy with the EIP-1559 changes.

I will look into this (and a few other issues) early this week. I suspect it will be an easy change, I mainly am interested in why this changed; it used to be TS didn’t care about extra properties, only missing ones.

I wonder if they changed how types vs. interfaces work regarding object literals. I just need to look into it to find the best solution; ideally solidity adding new keys shouldn’t break JsonFragments. :)

From the interfaces docs:

_Object literals get special treatment and undergo excess property checking when assigning them to other variables, or passing them as arguments. If an object literal has any properties that the “target type” doesn’t have, you’ll get an error:_

I think it's been around for a while, looks like since v3.

It's just that in most cases you'd end up assigning it to the type Fragment vs declaring the object as as a Fragment. The former doesn't do excess checks, so it would work fine.

Coolio. I've tested and added readonly internalType?: any to minimize the impact on backwards compatibility. The property isn't used by ethers, but in v6 I'll compare to the schema and make sure the field types match up.

This has been fixed in 5.4.0. Sorry for the delay. Try it out and let me know how it works for you. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Tomix3D picture Tomix3D  Â·  39Comments

elenadimitrova picture elenadimitrova  Â·  28Comments

dev1644 picture dev1644  Â·  42Comments

fmsouza picture fmsouza  Â·  51Comments

subramanianv picture subramanianv  Â·  34Comments