Today’s web linters are great.
ESLint is robust and has a huge ecosystem of plugins and configs.
Newer native speed linters such as Biome, deno lint, and Oxlint are fast and easy to set up with their own burgeoning ecosystems.
I’ve been working on TypeScript linting for almost a decade. I started contributing to TSLint community projects in 2016 and am now a member of the typescript-eslint and ESLint teams. Based on those years of various linters, I’ve collected a large set of design ideas that I want to try.
💡 This post is the fourth and final in a series:
High-Level Points
Those posts have a lot of ideas I’m excited about. You can totally skim this list, it’s huge!
- Part 1: Architecture:
- Hybrid core: native speed parsing for performance; TypeScript for approachable rules
- TypeScript For Type Awareness: directly using TypeScript for type aware rules
- Type-Aware, Always: removing the need to delineate or configure type-awareness
- Built-In TypeScript Support: building TypeScript support in core, rather than as a plugin
- Core Common Languages: additionally including universally relevant languages in core
- Formatting Coordination: saving users from having to configure a formatter separately
- Embeddable by Design: to deduplicate running type checking in CI and locally
- Rich Cross File Fixes: for more powerful rule codemods
- Cross File Caching: to avoid re-running lint rules on unchanged files
- Watch Mode: for even faster local CLI dev loops
- Part 2: Developer Experience:
- Only Errors: eliminating complexity and confusion around warnings
- Comprehensive Rule Reports: enforcing friendly and informative messaging
- Comprehensive Rule Documentation: similarly for documentation pages
- Standardized Rule Metadata: for consistent names, descriptions, and other info
- Typed Rules: for TypeScript-level rule option help
- Typed Plugin Settings: so plugins can define and use them safely
- Typed Configuration Files: helping users write config files with type safety
- Inline Snapshot Unit Tests: for rule tests that are easy to write and maintain
- Part 3: Ecosystem:
- Community Discord: aligning with the common community platform
- Shared Glossary: setting up consistent terminology across the ecosystem
- Common Core Rules: expanding core rules to cover ~universally useful cases
- Community Organization: assisting maintenance of high-priority rules
- Plugin Registry: centralizing a place to discover and register plugins
- Config Initializer: using the registry for starter config generation
- One-Way Compatibility: porting existing use cases to the new architecture
Even if you just read those high-level points and/or don’t work on linters yourself, I hope you’re at least excited about the potential for a linter that embraces all those new strategies. I think trying these ideas out will help take us to a much more pleasant and productive linting experience.
Flint
Speaking of which — I’m going to try these ideas out! I’m finally writing my own TypeScript linter. It’s just a prototype for now, with two intended purposes:
- To try out these ideas and see how they work in practice
- To get me deep experience in writing a linter, so I can better contribute to real-world linters
The new linter branding is Flint: A fast, friendly linter ❤️🔥.
Flint is extremely early stage at the moment. I’m hoping to get a usable CLI prototype with some of those features some time in summer 2025. I doubt it’ll have even a majority of the features in 2025. If you’re interested in following along -or even better, helping out-, you can check out the Flint Discord and Flint GitHub repository.
Please feel free to open issues or PRs. Or just reach out to me on Bluesky. I would love to hear your thoughts on this post, linting in general, and the Flint project.
Thanks for reading!