If you just use linting for checking a bit of stylistic policy, any replacement might be fine. However, linting is much more than that and if you are depending on third party rules or writing your own ([link redacted]), there is no way around ESLint.
Adding logic into linters blurs separation of concerns, adding unnecessary complexity akin to an extra programming language.
Linting in essence should be orthogonal to development — a layer that enhances code quality without being fundamental to the code’s functionality. By overextending linting, we risk creating a maintenance burden and an additional learning curve for developers.
Linting is a great tool and but as with any great hammer it’s easy for lots of things to start to look like nails.
It might be better to have some other tool to do pluggable static analysis, but the fact is that there isn't one. And eschewing project-specific static analysis entirely would be giving up far too much.
Two examples:
- we have an API like dbModel.getValue() that subscribes the current view to any change in an entire database row. We noticed this lead to UI performance issues from components over-rendering. To deprecate, I wrote a rule to transform dbModel.getValue().specificProp to dbModel.getSpecificProp(). We can’t remove the getValue method since there’s times you really do need it, but we can automatically switch new code written to a more performant specific call for many cases.
- We use a lint rule to enforce that API endpoints and queue worker jobs have ownership and monitoring rules specified. We could use the type system to strictly enforce this, but we want to support gradual migration as well as suggest some inferred values based on the identity of the author. Using a lint with ratcheting means newly added cases are enforced but easy to add, and old cases can/will adopt over time.
I want to find the time to write a blog post about this, I think it’s a pretty handy pattern.
I guess that's what I disagree with. Yes, it adds complexity of its own, just like types do. And I still favor solutions that are based on types for most things, but more and more I try to go this route. They are surprisingly easy to write.
https://github.com/oxc-project/oxc/tree/main/crates/oxc_quer...
I'm the Trustfall maintainer, happy to answer questions about the query engine or how oxlint or cargo-semver-checks use it.
I also recently gave a talk at P99 CONF on how cargo-semver-checks used Trustfall's optimizations API to get a 2000x speedup: https://www.youtube.com/watch?v=Fqo8r4bInsk