Hi all,
The last of the UI roadmap threads, after Path to Vite and Path to Vitest. This one is adopting TypeScript, and it depends on the first of those, so it goes last.
What TypeScript is
TypeScript is JavaScript with static types: annotations a compiler checks and then erases, so what ships is ordinary JavaScript. A renamed API field or a prop of the wrong shape becomes an editor error rather than a broken screen, and adoption is per file.
What the UI has today
Nothing, and this is the part worth reading twice. typescript sits in devDependencies at ^6.0.3 and nothing in src uses it: there are no .ts or .tsx files and no tsconfig.json. The only references are config/modules.js and config/webpack.config.js, resolving its path for a CRA type checker that has nothing to check.
There is no type information from the other direction either. prop-types appears in no source file at all: the one match anywhere in the tree is a translation catalogue. So across 1,627 .js and .jsx files, 552 of them tests, nothing describes the shape of anything.
Why it goes after Vite
Vite makes adoption close to free, because esbuild strips types as part of the transform with no separate build step to configure. Doing this first would mean wiring ts-loader or the babel TypeScript preset into the ejected CRA config, which is work that gets deleted in the same change that removes webpack.
The approach
Not a conversion project. allowJs on, both extensions compiling side by side, and the tree converts as it is touched:
- New files land as
.ts or .tsx.
api/ first, because typing the API client is what makes every caller benefit at once.
util/ and the hooks next, for the same reason.
- Screens and components as they come up for other work, never as a pass of their own.
What it buys
The API client is the strongest case. The UI talks to an API whose serializers change with the platform, and today nothing connects a renamed field to the screens that read it: it surfaces as undefined at runtime, on whichever screen someone opens first. Types turn that into a build error listing every call site.
It also gives editor completion across a codebase where the shape of a prop is currently only discoverable by reading the component that consumes it.
The honest cost
This one does not finish. A mixed tree is the normal steady state for years, and the value arrives in proportion to how much of the high-traffic code is converted rather than at some completion point. That is a different kind of commitment from the other two threads, and worth agreeing on deliberately rather than discovering at file 200.
Precedent
AAP's own UI is TypeScript throughout, so this is the one place in the frontend stack where they are ahead of us rather than behind. Worth noting we would be adopting the 6.x already in package.json, not the 5.5 pinned over there.
Thanks for reading.
Pull requests