Excessive type inference prevents code reuse, and hurts ecosystem #3550
Unanswered
KholdStare
asked this question in
Idea / Feature Request
Replies: 1 comment 1 reply
-
Agree that types can improve (simpler, better defaults, etc.) and it's on the loose roadmap of future improvements. |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Check existing issues
Viem Version
2.26.0
Current Behavior
To start off, the overall API "shape" is great and is an improvement over ethers.
However, using viem/wagmi beyond just directly calling it is basically impossible because of the excessive use of type inference. I have lost hours and hours of productivity when trying to make any generic wrappers of wagmi/viem functionality. Most of the Ethereum community has embraced viem and wagmi over ethers, but I think the ecosystem is now actively being stifled by the inaccessibility of reuse of any types provided by viem. Let me give a few examples.
Because the type safety needs to be maintained throughout with type inference, that means the crazy types have to be added at every single layer. This means users who want to use the viem/wagmi API beyond "dumb/direct" calls are forced to wrestle with pages and pages of arcane typescript errors in order to add it to their layer. This is like the most extreme version of a leaky abstraction, where every single lower-level detail is always bubbled up to the top in the types.
Type inference of function names and arguments from the ABI is great. However, anything beyond that, such as Chain, Account, RpcSchema inference is just overkill and I guarantee you the vast majority of users do not care and will not benefit from this. Having looser types for this will drastically simplify your implementation, make the source way more readable (I try to read the source to understand concrete type definitions to no avail), and allow others to wrap viem/wagmi functionality in their own code bases. If there is something special that is "keyed off" of the custom Chain type, then isolate it to that special function - just have a runtime test for a flag that the chain is "special". Then you don't have to polute 99% of the API for the marginal benefit of 1% of the API.
Even for argument type inference you should be able to isolate it to a single function, and not have it infect everything. Have a helper function that does the inference, and return a strong type that declares the input has been validated. That validated type can then be used in the rest of the API.
I have a strong background of 10+ years of hardcore C++, and I feel like a "pig in mud" when doing C++ template metaprogramming. However, it has its place, and I would not subject it on users of basic APIs. The same thing applies to typescript type wizardry. I don't want to learn the ins-and-outs of yet another metapgrogramming dialect, just so that I can make a simple wrapper of a javascript function. It's absurd.
As a barebones example of where this bites us, imagine we have a "standard procedure" of handling transaction simulation and contract writes - how we handle errors, etc. I want to wrap it in a simple abstraction. Here is some incomplete code one could write:
This doesn't work (adding inference doesn't really help either), and here is one of the errors in all its untruncated glory (please scroll sideways):
Expected Behavior
No response
Steps To Reproduce
No response
Link to Minimal Reproducible Example
No response
Anything else?
No response
Beta Was this translation helpful? Give feedback.
All reactions