enketo-core icon indicating copy to clipboard operation
enketo-core copied to clipboard

Gradually adopt TypeScript

Open eyelidlessness opened this issue 2 years ago • 0 comments

I'd like to begin to gradually adopt TypeScript in enketo-core. I intend to open a similar issue across several Enketo projects, but I'm starting here because I think it'll have the most immediate benefit. I'm opening this issue to ask for feedback in case other contributors have concerns, questions, or objections.

Motivation

Even without introducing type checking, static types:

  • help to document state and data flow throughout a codebase
  • aid code navigation and understanding code dependencies
  • improve editor support for automated suggestions, imports and refactors
  • help to prevent regressions, by providing immediate in-editor feedback on common mistakes at interface boundaries
  • can help to produce simpler and more understandable interfaces, and help to refactor more complex or hard to understand interfaces

Eventually adding type checking will provide another safeguard, allowing a whole class of mistakes to be caught during development and in CI.

Why gradual?

Migrating a large codebase from JavaScript to TypeScript is quite a task, and can be error prone and a workflow disruption. Thankfully, TypeScript has a great gradual adoption story. So great that the process is already well underway, and has been for years. JavaScript is already valid TypeScript, and JSDoc type annotations are valid TypeScript types. The TypeScript language server is used in VSCode (and other projects) to provide static analysis of plain .js files.

This is great, and some people even advocate for JSDoc type annotations as a permanent TypeScript adoption strategy. That's a valid option, but JSDoc types have some limitations, and they're cumbersome both to write and read.

Why now?

I've spent some time recently thoroughly documenting existing state and data flow for key areas of enketo-core which are some combination of:

  • High risk of regression
  • Hard to understand, follow, or find
  • Unclear in intent
  • Performance bottlenecks
  • Barriers to effective maintenance and feature work
  • High value targets for refactor

This documentation effort is ongoing and will continue. I plan to post a related issue tracking that. My goal is that most if not all of the work product comes in the form of static types and additional or improved inline JSDoc comments.

How

  1. Continue documentation, producing static types where possible.
  2. When introducing types and/or inline documentation changes to a module, first git mv it to have a .ts extension. This will help ensure continuity of git history.
  3. Add related types and comments across several modules in isolated commits, both to maintain a clean git history and to aid future navigation between them.
  4. Include additional navigation aids where it would be helpful (e.g. indirections between highly dynamic types and affected data flow points; a good example is evaluation cascade functions called by DataUpdate and AddRepeat event handlers). This will likely generally be handled by @see/@link JSDoc tags.
  5. As types are introduced, finding existing bugs is inevitable. These will be fixed along the way.
  6. If clearly high-value/low-risk minor refactors arise, they may be included with appropriate prior discussion.

Risks

I don't consider this particularly high risk (and I consider it overall a risk reducing effort), but I will acknowledge there are some areas of risk:

  • TypeScript isn't for everyone. It adds some new syntax, and some concepts not everyone is familiar with. Even gradual adoption might be a barrier to some contributors. That said, TypeScript adoption has accelerated for several years and has become a baseline assumption for quite a lot of the ecosystem.
  • Build and code quality tooling can be hard to set up, and can slow down work. Thankfully, this is already 99% solved in enketo-core (as well as enketo-express). Only a couple small config changes are necessary to include TypeScript files in the build, linter and test runner. And the build tool (ESbuild) is already incredibly fast.
  • More git history noise. I think this will be much less disruptive than, for instance, the code style changes in #866.

Anything I haven't thought of? Let me know!

eyelidlessness avatar Jun 02 '22 19:06 eyelidlessness