Making TypeScript Tools Safer and Smarter

Published: (December 12, 2025 at 08:38 PM EST)
3 min read
Source: Dev.to

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 as any, or where a whole generic type uses any.
  • The issue was that a nested any property 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 .publicodes files.
  • Previously, the server treated all .publicodes files 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.json or .publicodes.config file) 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.
Back to Blog

Related posts

Read more »

Testing in Umami codebase - Part 1.2

Inspired by BulletProof Reacthttps://github.com/alan2207/bulletproof-react/tree/master, I applied its codebase architecture concepts to the Umami codebasehttps:...