Making TypeScript Tools Safer and Smarter
Source: Dev.to
Overview
For the past few weeks I focused on open‑source contributions that impact real TypeScript developers daily, tackling issues beyond simple styling fixes. I worked on two projects:
- typescript-eslint – a collection of ESLint rules that keep TypeScript code safe and consistent.
- publicodes/language-server – a VS Code extension providing language‑server features (diagnostics, completion, hover, go‑to‑definition) for the Publicodes language.
These contributions let me work on both static‑analysis rules and an actual language server.
typescript‑eslint contribution
I addressed a feature request for the no-unsafe-* rules to detect unsafe any values inside object types, not just at the top level.
- The existing rules (
no-unsafe-argument,no-unsafe-assignment, etc.) already blocked obvious cases where a parameter or variable is typed directly asany, or where a whole generic type usesany. - The issue was that a nested
anyproperty could slip into a stricter object type without warning. - I updated the internal helper used by these rules so it now walks into objects, arrays, and other containers to find hidden unsafe
anys. - Added tests confirming that the exact example from the issue is now reported, while safe versions still pass.
- Cleaned up parts of the repository that started failing under the stricter checks.
publicodes language‑server contribution
I added support for multiple models in a single workspace.
- The language server integrates the Publicodes language into editors like VS Code, offering semantic highlighting, diagnostics, and go‑to‑definition for
.publicodesfiles. - Previously, the server treated all
.publicodesfiles in a workspace as belonging to one giant model, which caused problems in monorepos or multi‑folder workspaces where separate models should remain isolated. - My fix introduces a model boundary (e.g., the nearest
package.jsonor.publicodes.configfile) and groups files by that boundary. - Each group receives its own internal data structures and engine instance, so diagnostics, hovers, completions, and definitions for a file now go through the model that owns that file instead of a global one.
Process and Reflections
The work was incremental:
- I spent considerable time reading unfamiliar code and understanding how pieces fit together.
- In
typescript-eslint, I navigated the type utilities before writing code, repeatedly running the test suite and adjusting changes as new failures appeared. - In the language server, I traced file discovery, rule storage, and diagnostic production, then carefully threaded the new model information through those paths.
- Breaking the work into smaller steps (first tracking models, then updating parsing, then updating validation) proved essential.
Looking back, I achieved my original goal:
- Stayed within the TypeScript tooling space.
- Tackled tasks slightly above my comfort level and persisted through complex logic.
- Recognized the downside of picking overly complicated issues—overthinking and getting stuck—but overall gained confidence in contributing to serious open‑source projects.
Future Work
- Improve planning of contributions to allocate more time for reviews and polishing.
- Continue pushing myself to produce real, useful contributions in the TypeScript ecosystem.