Life after TypeScript
Based on Theo - t3․gg's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Motion’s TypeScript monorepo delivered strong full-stack type sharing, but scaling exposed persistent tooling and workflow pain: language server crashes and slow CI/typechecking.
Briefing
Motion ran a massive TypeScript monorepo for years—about 2.5 million lines of code at peak—and still decided to move off TypeScript. The core takeaway isn’t that TypeScript is “bad,” but that scaling a large TypeScript organization can become a developer-experience bottleneck: editor instability, slow CI, and compiler/tooling pain can start to outweigh the benefits of full-stack type sharing.
TypeScript’s original promise at Motion was real. It enabled rapid validation of ideas, let teams work across front end and back end with shared types, and supported code reuse across a React web app, React Native mobile, an Electron desktop app, and infrastructure-as-code via Palumi. Motion also leaned on the ecosystem to unify development workflows and share backend/API type definitions across multiple products.
Over time, the “share everything” dream didn’t fully materialize. Differences in React Native versus the web meant UI and component sharing often failed in practice. Motion found that developers frequently forgot mobile when changing shared libraries, causing repeated breakages. For some screens, performance demands forced a retreat from React Native: a calendar view reportedly hit around 190% CPU, with the underlying issue framed as costly back-and-forth between JavaScript and native layers when nested components repeatedly fetch data. The fix wasn’t abandoning the stack entirely, but changing strategy—prototype features quickly in React Native, then convert to native selectively once usage and performance justify it.
On the TypeScript side, Motion described the familiar pain points of a growing codebase: TypeScript language server crashes, CI pipelines that regularly took 20+ minutes, and a long wait for upstream improvements. They pointed to TypeScript Go as a major effort aimed at improving performance, but also highlighted stopgaps and ecosystem upgrades. Zod v3 triggered TypeScript compiler max recursion depth issues, leading them to wait for Zod 4. They also cited improvements from Zod 4 and targeted work on TRPC, including fixes that reportedly improved TypeScript-related performance by up to 80% for some applications.
Database tooling added more friction. Prisma was criticized for destructive behavior—deleting an entire table when a where clause evaluates to undefined—along with other bugs. Motion described Prisma as improving over time, but also supported alternatives like Drizzle, which they viewed as a longer-term option.
The most consequential part of the decision was organizational control. Motion’s argument, as reflected in the discussion, is that waiting on community timelines can slow a scaling startup. TypeScript’s ecosystem is vibrant, but the team couldn’t afford to treat core build and tooling reliability as someone else’s roadmap.
Instead of swapping languages for performance alone, Motion chose C# and .NET for a mix of productivity and guardrails: a mature ORM story via Entity Framework Core, strong tooling via Roslyn, and a large ecosystem. The transition was also framed as lower-risk because C# and TypeScript share familiar syntax patterns (async/await, nullable types, arrow functions). The broader debate in the discussion then turns to tradeoffs: moving off TypeScript can reduce editor/build pain, but it can also shift complexity into backend infrastructure and type synchronization elsewhere. The bottom line is less “leave TypeScript” and more “don’t bet your company’s velocity on tooling that can’t keep up with your scale.”
Cornell Notes
Motion’s TypeScript monorepo delivered real full-stack benefits—shared types across React, React Native, Electron, and Palumi—but the expected “share everything” payoff weakened as platform differences and developer workflow gaps caused breakages. Performance issues on mobile (notably a calendar screen hitting ~190% CPU) pushed Motion toward a hybrid approach: build new features in React Native for speed, then convert performance-critical parts to native. On the TypeScript tooling side, language server crashes, slow CI, and compiler limits (including Zod v3 max recursion depth) created persistent friction, with improvements tied to TypeScript Go, Zod 4, and TRPC-related compiler fixes. The decision to move off TypeScript centered on control: startups can’t afford to wait for community timelines when reliability and iteration speed are business-critical.
Why did Motion’s “share code everywhere” strategy fail to fully deliver, even with TypeScript?
What mobile performance mechanism was blamed for the calendar screen’s CPU spike?
How did Zod and TRPC relate to TypeScript compiler performance problems?
What was the critique of Prisma, and why did Drizzle enter the picture?
What was the decision logic behind moving from TypeScript to C#/.NET?
How did the discussion separate different kinds of “scale” and performance?
Review Questions
- What specific developer-experience failures (editor/CI/typechecking) pushed Motion toward reconsidering TypeScript, and how were they tied to particular tools like Zod and TRPC?
- Why did Motion’s approach to React Native evolve into a “React Native first, native later” strategy? Identify the performance mechanism described.
- What criteria made C#/.NET a better fit than other statically typed options for Motion’s constraints, and how did Entity Framework Core factor into that choice?
Key Points
- 1
Motion’s TypeScript monorepo delivered strong full-stack type sharing, but scaling exposed persistent tooling and workflow pain: language server crashes and slow CI/typechecking.
- 2
React Native UI sharing with the web often underperformed because the platforms differ; Motion saw breakages when shared libraries weren’t tested with mobile in mind.
- 3
A mobile performance bottleneck was linked to nested rendering and repeated data fetching across the JS-to-native boundary, motivating hoisted data fetching and selective native conversion.
- 4
Zod v3 contributed to TypeScript compiler max recursion depth issues, and Motion waited for Zod 4 while also relying on TypeScript Go and TRPC/compiler fixes for performance improvements.
- 5
Prisma faced serious reliability concerns (including table deletion when a where clause is undefined), leading Motion to sponsor Drizzle as a longer-term alternative.
- 6
The decision to move off TypeScript centered on organizational control: startups can’t afford to depend on community timelines for core build and editor stability.
- 7
C#/.NET was chosen for guardrails and productivity, with Entity Framework Core and Roslyn-based tooling cited as major advantages for enterprise-style CRUD workloads.