The only change is that type checking is now it's own subcommand: `deno check`, instead of happening as part of `deno run`.
See last releases' blog post for the rationale: https://deno.com/blog/v1.21#deno-check-and-the-path-to-not-t...
deno check is very welcome, but I think I would have preferred a --nocheck option when running instead of a --check option
That's surprising/depressing, but kudos I guess for doing user research and listening to what the majority wants
Why? TypeScript type-checking is slow. Furthermore it's common when refactoring code that you break code in many places, but that you want to run the code you are actively working on and iterate on it (perhaps further changing the shared types in the process) before going through and fixing uses of that code everywhere.
As long as you have CI process enforcing the type checking, there's no real disadvantage to this approach.
Before Deno this was more tolerable because the ecosystem was so messy to begin with; libraries that lacked types, APIs that were never designed with types in mind. But Deno is in many ways a fresh start, and given that opportunity I'd prefer it if we said "typed and passing code is the default, you have to go out of your way if you want to violate that convention". It's a shame to leave the door wide open for a slow-rot of type failures, especially when Deno already supports plain JS files for the cases where you really need to skip writing types.
I can understand eg. edge providers wanting to skip running the check every time a worker spins up, but I've never felt like checks were slow enough that they needed to be skipped in a dev environment (and therefore turned off by default)
I also love how Deno is nicely maturing. Can't wait to find a problem to solve with Deno!
Shouldn't matter if it's a dependency that's broken, or my code, if it's broken it's broken regardless of who wrote it. Failing at runtime instead of start time because of a bad dependency is a bad behavior.
One of the under-appreciated superpowers of gradually typed systems like TypeScript is the ability to ignore errors in parts of the codebase I don't care about right now, and focus on exercising the runtime behavior of the code paths I'm currently working on, because I can always have a working program that can be executed (and possibly crash at runtime) regardless of what the static analysis tells me is wrong with it.
Without this, large scale changes tend to become extremely painful all-or-nothing affairs that have to be applied codebase wide at every iteration, and I only find out the change doesn't work the way I expected at runtime after I've already done all the work applying it to everything across the board, and have to repeat the whole process over and over again.
If you really wanted to import a broken dependency, at least with typescript you can compile the dependency to plain javascript which will remove all types (and thus all type errors as well). But to disable type checks by default for a typed language seems a bit odd.
And to be clear, this is still an "all-or-nothing" approach. When you disable checks, it's "nothing". Deno will still compile even if there are type errors in your own code. (At least that's what I'm assuming, I haven't tested the nochecks option yet. Please correct me if I'm wrong)
This is the frustrating part with using a mixed typed ecosystem.
That's not noise. That is a bug.
There's a huge performance overhead to run type checking, so the changes are for it to only be run for development/bundling workflows and be opt-in otherwise.
The separate code-generation combined with esbuild means that I can hit “Debug” and my app builds and starts up almost instantly.
The type-checking is done as a commit hook, so if there are any type errors they will be fixed once im done working on whatever small change. Any dependency which doesn’t have valid types probably has bigger issues, but during active development, active-file type-checking is usually enough.
[0]: https://deno.com/blog/v1.21#deno-check-and-the-path-to-not-t...
Code is still being type checked, just not by default at runtime anymore. You can also just do `deno run --check=all main.ts` to check at runtime by the way.
The functionality isn't even being removed, it's just moved around and some defaults are being changed :)
That's a pretty big caveat. In most cases "not by default" means "hardly ever".
I feel like the change would go over better if you were more honest about the only real reason to do this - speed. If you just said "type checking is too slow for `deno run`. We'd like to have it type check then but upon reflection we think the speed cost is worse than the cost of moving type checking to a non-default command."
That's very reasonable. "We don't think types should be checked by default" is just pretty crazy IMO.
Also, don't you cache the output so it's only slow on the first run?
> Up to now, deno run has always automatically performed type checking on the code it was about to run, just before running it. This can sometimes be a nice user experience, but more often than not it is not what you want. The reason for this is often that type checking is really slow: it is often by far the single largest factor impacting the startup performance of your application.
(This is of course assuming that most type errors are largely localized enough that your IDE will find them).
Also, we already have a "do-not-typecheck" flag (`--no-check`), we were just seeing in real world usage that nearly everyone who uses Deno professionally would enable this flag for inner loop development, and leave type checking up to CI and their IDE. If 95% of your users use a flag that changes a default, then that changed value should probably be the default (resulting in a better experience for most people) :)
That makes sense, thanks.
> Also, we already have a "do-not-typecheck" flag (`--no-check`), we were just seeing in real world usage that nearly everyone who uses Deno professionally would enable this flag for inner loop development, and leave type checking up to CI and their IDE. If 95% of your users use a flag that changes a default, then that changed value should probably be the default (resulting in a better experience for most people) :)
I'm still not a big fan of changing defaults for commands that may e.g. be part of scripts, outside major version jumps, but I get the motivation if the no-check flag was in fact far more oft-used than the default behavior.
It worked pretty well for the most part, and I would recommend looking into this for most teams since it's a pretty quick win. Most typecheck steps went from minutes to low-double-digit seconds (admittedly still slower than I would have hoped).
But occasionally there would be gigantic spikes back to minutes for seemingly small changes that seem like they should have been incrementally check-able. I suspect these might have something to do with circular dependency chains, but didn't have bandwidth to dig deeper.
I wish TypeScript's incremental checking mechanism and file formats was a bit better documented and less opaque, so people could better reason about and optimize typechecking performance, and possibly build support into other systems to perform & share some of the analysis they're already doing to avoid wasted work. That and to make it less of a giant blob for the entire codebase, and more of a set of files that are incrementally and individually update-able for better cache granularity and faster updates.
Deploy JavaScript Globally
Instant deployments
Located in 32 regions worldwide
Zero config, zero maintenance
TypeScript, Wasm, ES Modules