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 be 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!