hardhat
hardhat copied to clipboard
Make typechecking opt-in instead of opt-out
Typescript projects are always typechecked. You can opt-out of that with TS_NODE_TRANSPILE_ONLY=1
, but most users don't know about this and it means unnecessary friction (since most of the time you probably don't want to typecheck).
We want to improve this. There are some things to do:
- Consider replacing
ts-node
withswc
. Alternatively, just always set the transpile-only flag when usingts-node
. - Add some mechanism for explicitly typechecking the project, like a
typecheck
flag (or we could just use the existingcheck
task). - Document this where appropriate.
This issue is also being tracked on Linear.
We use Linear to manage our development process, but we keep the conversations on Github.
LINEAR-ID: ef1ee6e9-46ae-482a-826a-2519967d3aab
@fvictorio I'd recommend staying on ts-node. I've been working with swc for some gulp stuff and it is still very experimental and contains significant bugs (such as segfaulting when having 2 copies on your system).
fwiw, ts-node 10 supports .cts
extension, which would allow hardhat.config.cts to remain compiled to commonjs even if it is within a type: module
project.
@phated thank you for the tip. We are currently on the fence about using ts-node or swc and this might be the tie-breaker we needed.
@fvictorio Have you considered stuff like esbuild / esbuild-kit (https://github.com/esbuild-kit)? We leverage that toolchain to enable vitest
to work with hardhat. And I'm also happily using tsx
and tsup
elsewhere.
Not having to pass everything always through ts-node (and particularly the typechecking of course), comes with some significant performance gains for larger codebases.
EDIT: Another issue with ts-node is that it still doesn't support path mappings. https://github.com/TypeStrong/ts-node/pull/1585
Maybe this is the time to re-evaluate full ESM compatibility? <3 :-)
Maybe this is the time to re-evaluate full ESM compatibility?
"Full ESM compat" is impossible in hardhat before the next major. Hardhat's task system relies entirely on the order which tasks are imported and ESM is always async, which means order is not ensured whatsoever.
Franco and I are looking into smaller changes that will allow hardhat to continue operating in CJS mode inside type: module
projects.
Maybe this is the time to re-evaluate full ESM compatibility?
"Full ESM compat" is impossible in hardhat before the next major. Hardhat's task system relies entirely on the order which tasks are imported and ESM is always async, which means order is not ensured whatsoever.
Franco and I are looking into smaller changes that will allow hardhat to continue operating in CJS mode inside
type: module
projects.
It's not impossible. Hard, to refactor without breaking changes, yes maybe ... But not impossible! I've discussed this before and looked into it for a few hours. It can be accomplished by separating and isolating all the internal components from the CLI and the "task runner" parts. For more tightly integrating with testrunners like vitest, jest, et. al this is arguably even a requirement anyways because you really don't want to take the test process parallelization capabilities away from those which you do if you wrap it upside down with the hardhat task runner first.
Hard, to refactor without breaking changes, yes maybe ... But not impossible!
It's not about the hardhat implementation itself. It would be an ecosystem level breaking change. Everyone's hardhat.config file would be broken because task order cannot be guaranteed.
Again, we are discussing workarounds that will allow hardhat to exist alongside a type: module
project.
What I'm saying is: Let's modularize the core components of hardhat and expose some of the underlying bits that are also useful outside of the task runner mode of operation (hardhat evm, etc.) programmatically.
First of all, this would make customization and recomposability much easier: It's currently rather fiddly to access underlying functionality, bypassing the task runner / script / cli layer.
Secondly, it would allow for these components to then be defined as ES modules. The part that you are worried about, the hardhat
package, task runner, config loading, etc. can remain CJS and simply wrap the ESM exports using async dynamic imports.
That way, everyone gets what they want: Those who fancy to use the internal modules conveniently, bypassing the hardhat cli to e.g. utilize the hardhat evm from within vitest or else can do so while those who want to continue to use the hardhat cli in its current form can do that too. It doesn't have to be either / or.
Thanks for the chiming in here, @phated and @fubhy! 💖
What I'm saying is: Let's modularize the core components of hardhat and expose some of the underlying bits that are also useful outside of the task runner mode of operation (hardhat evm, etc.) programmatically.
This is still something we want to do, as we discussed some time ago. We haven't had enough bandwidth yet, but we will soon. We've put a ton of work into growing the team lately.
Once we have a clear timeline to when this can happen I'll reach out. We may do it when we switch Hardhat Network's backend to rust, as now we use some ethereumjs' apis in our codebase (e.g. in our Blockchain).
The part that you are worried about, the hardhat package, task runner, config loading, etc. can remain CJS and simply wrap the ESM exports using async dynamic imports.
Yes, I think this is what Blaine means by not being able to add full support. Right now your config needs to be CJS (and hence everything imported from it), or the plugin system will break in ugly ways.
Thanks @alcuadrado. Just to be clear I definitely don't want to derail this effort or distract you from your roadmap. I am just really eager to delete as much of the workarounds that are currently needed for our use-case as possible. I love deleting code :-). So apologies if I pushed this a bit off-topic.
This is what we need to do:
- Transpile-only by default. That's mainly about changing this line and this line so that they require
"ts-node/register/transpile-only"
instead (unless typechecking is enabled, see next item). - Add a
--typecheck
global flag. When used,ts-node
will perform typechecking as it does now. - Make the necessary changes in the typescript guide.
Also, using --typecheck
should throw if the project does not support typescript.