TypeScript Adoption Rate Among Top npm Packages 2026
TL;DR
TypeScript has won the npm ecosystem at the top. 95% of the top 100 packages either ship TypeScript types or have high-quality @types/ support. But adoption falls off rapidly in the long tail — only ~40% of all npm packages have any TypeScript support. The gap between top packages and average packages has never been larger, and it's accelerating as TypeScript-first packages consistently outperform JavaScript-only alternatives.
Key Takeaways
- Top 100 packages: 95% TypeScript support (bundled or @types/)
- Top 1,000: 89% TypeScript support — the professional tier
- All packages: ~40% TypeScript — long tail is still mostly JS
- TypeScript-first (bundled types) vs @types/ is growing: 78% bundled among typed packages
- TypeScript usage: ~68% of JS developers use TypeScript (State of JS 2025)
The Adoption Curve
TypeScript support across npm (2016-2026):
Year Top 100 Top 1000 All packages
2016: 25% 15% 5%
2018: 45% 30% 12%
2020: 65% 50% 22%
2022: 80% 70% 32%
2024: 90% 82% 38%
2026: 95% 89% 42%
Observations:
→ Top packages: near-universal TypeScript (95%)
→ Long tail: growing but slower (only 42%)
→ The gap is widening: top packages normalized TS; long tail catching up slowly
Why the top converged faster:
→ High-profile packages face developer pressure ("why no types?")
→ Open source maintainers are power users who want types
→ GitHub issues and PRs: TypeScript type requests are common
→ "TypeScript TS" badge on npmjs.com → download signal
TypeScript Support by Package Category
TypeScript adoption rate by package category (2026):
State management: 100% (zustand, jotai, valtio, redux-toolkit, xstate)
Build tools: 99% (vite, esbuild, rollup, webpack types, rspack)
Testing: 98% (vitest, playwright, testing-library, jest via @types)
Validation: 100% (zod, valibot, arktype, yup via @types)
ORM / Database: 95% (prisma, drizzle, mongoose via @types, knex)
HTTP clients: 92% (fetch, axios, ky, undici, ofetch all typed)
Web frameworks: 90% (hono, fastify, express via @types, koa)
Date libraries: 95% (dayjs, date-fns, luxon, temporal polyfill)
Auth: 90% (clerk, auth.js, lucia — all TypeScript-first)
CSS-in-JS: 85% (styled-components, emotion, panda css)
Charting: 75% (recharts, chart.js, d3 — d3 is complex types)
CMS integrations: 70% (varies widely)
Legacy utilities: 55% (many old utility packages still JS-only)
Unmaintained packages: <30% (abandoned packages rarely got types)
TypeScript-First vs @types/ Packages
// The distinction matters for quality:
// TypeScript-first: types are part of the package, maintained together
// package.json: "types": "dist/index.d.ts"
// Types updated with every release
// Types are tested in the same test suite
// Examples: Zod, Zustand, Fastify, TanStack Query, Drizzle, Hono
// @types/: maintained separately on DefinitelyTyped
// Separate repo, separate contributors, can lag behind
// Types might be 1-2 minor versions behind
// Examples: @types/express, @types/node, @types/react
// The quality gap:
// TypeScript-first packages: types are usually precise and correct
// @types/ packages: quality varies widely
// - @types/react: excellent (maintained by dedicated community)
// - @types/node: excellent (Microsoft maintains)
// - @types/some-old-library: may be years out of date
// How to tell which you're getting:
npm view package-name --json | jq '.types, .typings'
// Returns path → TypeScript-first
// Returns null → check for @types/package-name on npm
Packages That Made the TypeScript Transition
# Early JavaScript-only packages that added TypeScript support:
# axios: v0.x was JS-only
# axios@0.20: bundled .d.ts files
# axios@1.0: full TypeScript rewrite of types
# Now: excellent TypeScript support, built-in
# lodash: added types via @types/lodash (community effort)
# lodash/fp types: separate @types/lodash-fp
# Still @types/-based but high quality (very widely used = well maintained)
# express: still @types/express
# express v5 (finally): improved API but still relies on @types/
# @types/express is maintained by the community, surprisingly good quality
# mongoose: added TypeScript support in v6+
# mongoose@6+: built-in types, model generics, query typing
# Before v6: only @types/mongoose (often wrong for complex queries)
# socket.io: excellent TypeScript support since v4
# Generic types for event names and payloads:
import { Server, Socket } from 'socket.io';
type Events = { message: (text: string) => void; join: (room: string) => void };
const io = new Server<Events>(); // Fully typed event names and payloads
Developer Usage Data
TypeScript usage (State of JS 2025):
"I use TypeScript" (by self-report):
→ Yes, exclusively: 45%
→ Yes, with JavaScript: 23%
→ No, but plan to: 14%
→ No, don't plan to: 18%
Total TypeScript users: ~68% (up from 45% in 2020)
By company size:
→ Startups (1-10): 60% use TypeScript
→ Mid-size (11-200): 75% use TypeScript
→ Enterprise (200+): 85% use TypeScript
By developer tenure:
→ <2 years experience: 45% TypeScript
→ 2-5 years: 65% TypeScript
→ 5-10 years: 72% TypeScript
→ 10+ years: 65% TypeScript (some "I prefer plain JS" in senior devs)
Why TypeScript adoption keeps growing:
1. AI code editors: Copilot, Cursor suggest type-safe code
2. Error catching: TypeScript catches entire classes of bugs at compile time
3. Refactoring: type-safe refactoring is dramatically safer
4. Self-documenting: types replace many code comments
5. Ecosystem: TypeScript-first libraries have better DX
The JsDoc Alternative
// Not everyone uses TypeScript — some use JSDoc for types
// JSDoc: type annotations in JavaScript comments, parsed by TypeScript
/** @type {import('express').Request} */
const req = getRequest();
/** @param {string} name @returns {string} */
function greet(name) {
return `Hello, ${name}!`;
}
// Downside of JSDoc vs TypeScript:
// → More verbose than TypeScript type syntax
// → Limited generics support
// → Can't import complex types as cleanly
// → Not enforced at file boundaries
// Who uses JSDoc:
// → Packages targeting multiple environments (some don't want TS build step)
// → Legacy codebases adding types incrementally
// → Projects where "zero build" matters (direct browser scripts)
// The trend: TypeScript is winning decisively over JSDoc
// JSDoc: ~12% of typed packages (down from 25% in 2020)
// TypeScript: ~88% of typed packages (up from 75%)
The TypeScript "Tax" That Isn't
// Common objection: "TypeScript adds complexity"
// Reality: TypeScript REMOVES complexity at scale
// Compilation step: true cost
// → tsc or vite/esbuild compile step
// → Adds 1-30 seconds to builds (parallel, so often negligible)
// → Type checking: separate from compilation (esbuild skips type-check)
// IDE support: massive productivity gain
// → Autocompletion for every import, every method
// → Inline error detection before running code
// → Safe rename refactoring across entire codebase
// Type errors found: average project
// → Converting JS codebase to strict TS:
// typically finds 5-20% of function calls with wrong argument types
// typically finds 10-30% of property accesses that could be undefined
// → Most of these become real runtime bugs eventually without TypeScript
// The real cost: strictness config
// tsconfig.json "strict: true" is uncomfortable for JS developers at first
// But teams that do it: significantly fewer production type errors
// Teams that don't: get TypeScript with the safety net partially removed
// Verdict: TypeScript's "tax" is a one-time learning cost
// Its benefit is continuous: every type error caught = one fewer bug
Why Some Packages Still Resist TypeScript
For all the ecosystem pressure toward TypeScript, a meaningful set of high-download packages still don't ship native types in 2026 — and some of the reasons are legitimate rather than mere neglect.
The CommonJS-first legacy problem is the most common cause. Packages like older versions of lodash and underscore were written before TypeScript existed and carry massive installed bases that make breaking changes economically and practically impossible. Their authors can't refactor the source to TypeScript without risking regressions for millions of existing consumers who rely on current behavior. The DefinitelyTyped ecosystem exists precisely to solve this: @types/lodash provides high-quality types maintained by the community, letting TypeScript developers consume lodash without requiring lodash itself to change.
The "JavaScript is the lingua franca" argument is the other major reason. Package authors targeting Node.js scripts, CLI tools, and non-TypeScript users want to ship plain .js files without imposing a TypeScript toolchain requirement on their consumers. For these authors, TypeScript feels like a dependency for the package author's convenience rather than a benefit for all users.
Type definition complexity is a third factor. For deeply dynamic packages — express middleware chains, plugin systems with open-ended extension points, event emitters with string-keyed events — generating accurate TypeScript types requires significant engineering investment that may not serve most users. The types for express's middleware chain have always been approximate; modeling the full generality of req.body, req.params, and plugin-extended properties requires workarounds that can feel worse than no types at all.
The practical outcome is that DefinitelyTyped has effectively solved the TypeScript consumption problem for the most popular packages without requiring upstream adoption. @types/node surpassed 50 million weekly downloads as of 2026 — a striking data point about how much TypeScript development happens against the Node.js runtime.
The TypeScript Transition Patterns
Packages that successfully migrate to TypeScript almost always follow one of three recognizable patterns, and the pattern chosen reveals a lot about the package's architecture and maintainership philosophy.
The gradual annotation approach adds JSDoc types first, requiring zero build changes — the existing .js files gain @type comments that TypeScript can read directly. This lets maintainers ship typed declarations to TypeScript consumers immediately while deferring the .ts migration to a second phase. Vite's internal approach to progressive typing reflects this philosophy: ship types consumers can use now, improve internal rigor incrementally. The advantage is that existing consumers see no changes to the published package; the disadvantage is that JSDoc types are harder to maintain than .ts source as the API grows.
The full rewrite approach is what TypeScript-native packages like tRPC and Zod did from day one, giving them a structural advantage over older alternatives. When types are part of the source from the first commit, every API decision is made with the type system in mind. The result is types that are precise and idiomatic in ways that cannot be retrofitted onto a JavaScript package. Zod's type inference — computing the exact TypeScript type from a schema definition — is only possible because the library was designed from the ground up to drive TypeScript's inference engine.
The dual package approach publishes both .js and .d.ts files via a build step, with "types": "./dist/index.d.ts" in package.json. This is the most common pattern for packages migrating from JavaScript to TypeScript incrementally. The source becomes .ts, the build produces the JavaScript consumers run and the declarations TypeScript reads. The ecosystem pressure to adopt this pattern has been immense: packages without bundled types see measurably reduced adoption from TypeScript projects, which now represent the majority of serious web development.
The 2026 Baseline: Native Types Are Table Stakes
The expectation bar for TypeScript support has risen sharply, and in 2026 it has effectively settled: native bundled types are the requirement for packages targeting TypeScript-first developers, and DefinitelyTyped is the fallback for legacy packages that cannot reasonably be migrated.
The DefinitelyTyped lag problem is the driving force behind this shift in expectations. Community-maintained @types/* definitions often trail the package by one or two releases. When a package ships a new API in version 4.2 and @types/package is maintained by a different set of contributors, TypeScript users may be waiting weeks or months before the types reflect the new surface. Worse, community types can have gaps or inaccuracies that the package authors themselves wouldn't make, because the type authors are reasoning about the API from the outside rather than from the implementation.
The shift is visible in new package launches: packages released in 2024–2026 almost universally ship native TypeScript types. The holdouts are legacy packages with large installed bases where a migration carries risk, and packages specifically targeting JavaScript-only environments like shell scripts or lightweight browser utilities that have no TypeScript users to serve.
For package authors evaluating whether to invest in TypeScript, the calculus is straightforward: native types are now a competitive requirement, not a differentiator. Absence of types is a friction point that costs downloads from the growing majority of TypeScript projects. For developers evaluating packages, a package without native types in 2026 is a yellow flag — worth pausing to ask whether the package is actively maintained, whether the DefinitelyTyped definitions are current, and whether a TypeScript-native alternative exists.
How Framework Ecosystems Differ in TypeScript Adoption Pressure
TypeScript adoption does not happen uniformly across the JavaScript ecosystem — it spreads through framework communities with very different velocities. The React ecosystem moved fastest because React's own patterns created natural pressure for types: the prop type problem (what does this component accept?) was never solved elegantly in plain JavaScript, and TypeScript's interface system answered it directly. Once major React tools like Redux Toolkit, TanStack Query, and Zustand shipped TypeScript-first APIs, the network effects compounded: using these libraries in JavaScript meant tolerating awkward .d.ts workarounds that TypeScript developers never encountered.
The Vue ecosystem followed a different trajectory. Vue 2's Options API was not TypeScript-friendly by design — the this context made type inference unreliable, and the community lived with it comfortably for years. Vue 3's Composition API was architected explicitly to solve this, making TypeScript a first-class citizen at the framework design level rather than an afterthought. The adoption jump in the Vue TypeScript ecosystem between 2020 and 2023 was sharper than React's because it was enabled by a deliberate rewrite of the underlying framework API surface.
Svelte and SvelteKit took a different approach again: they made TypeScript configuration a first-run decision rather than a gradual migration. The default npx create svelte prompt asks whether you want TypeScript support from the start, normalizing it as the default choice rather than an advanced option. This opinionated onboarding explains why Svelte-authored packages on npm have unusually high TypeScript adoption rates relative to the framework's overall download volume.
The Angular ecosystem is an outlier in the other direction: TypeScript has been mandatory since Angular 2 launched in 2016. The community never had the "should we use TypeScript?" debate that played out in React and Vue communities. Angular developers discovered TypeScript's tradeoffs at scale earlier than anyone else, which gave them a head start on the ecosystem dynamics — strict null checks in large codebases, the costs of overly permissive any usage, the value of discriminated unions — that the broader JavaScript community is still working through.
TypeScript in Non-Node Environments: Deno, Bun, and Edge Runtimes
The rise of alternative JavaScript runtimes has created a new front in TypeScript adoption where the dynamics are different from the Node.js npm ecosystem. Deno made the most consequential design decision: it treats TypeScript as a first-class language natively, without a separate compilation step. A .ts file runs directly in Deno the same way a .js file runs in Node — Deno handles the transformation internally, using V8 and a built-in transpiler. The practical effect is that TypeScript is not an add-on in Deno's ecosystem; it is the default language for Deno packages, and packages authored without TypeScript are the exception rather than the rule.
Bun takes a similar stance: TypeScript files execute directly without a separate tsc step. The result in practice is that the toolchain barrier to TypeScript adoption is nearly zero in Bun projects, which removes the compile-step friction that still deters some JavaScript-only developers in Node.js environments. When you do not need to configure tsconfig.json, set up a build pipeline, or think about .d.ts emission before you can run TypeScript code, adoption resistance drops considerably.
Cloudflare Workers and other edge runtimes have been TypeScript-native in their tooling from the start. The Cloudflare Workers template, Durable Objects template, and Hono's edge adapters all default to TypeScript without an alternative offered. When the platform scaffolding assumes TypeScript, the ecosystem packages targeting that platform follow. Hono, built explicitly for edge runtimes, is TypeScript-first. Its type-safe routing API — where URL parameters and query strings flow through the type system rather than being untyped strings — would not be architecturally expressible in plain JavaScript.
The implication for npm package authors is that TypeScript is now an environmental assumption across virtually every modern runtime target, not just Node.js with a TypeScript compiler. A package that does not ship types is a package that is friction in every major deployment environment, not just TypeScript-configured Node.js projects.
Compiler Performance at Scale: Where TypeScript Slows Down
TypeScript's compile-time performance is a genuine concern at large scale, and it is underreported in adoption discussions because most tutorials and documentation cover projects under ten thousand lines. Past that scale, the TypeScript compiler's architecture — which does full program analysis rather than file-by-file analysis — means that compilation time grows non-linearly with codebase size. Large monorepos with fifty or more packages run into tsc taking minutes rather than seconds for full type-checking.
The response from the ecosystem has been architectural rather than waiting for tsc to get faster. Bundlers like Vite and esbuild strip types using babel's @babel/plugin-transform-typescript or esbuild's own transformer — both of which simply delete type annotations without performing type-checking. This makes builds fast regardless of codebase size but moves type-checking to a separate process. The practical workflow in large TypeScript projects is: esbuild/SWC for fast builds during development, tsc --noEmit in CI for full type verification before merge. This separation of "remove types so the code runs" from "verify the types are correct" is how high-velocity teams avoid compile-time bottlenecks while maintaining type safety.
Project references, introduced in TypeScript 3.0, are the other major response to scale. They allow a monorepo to declare its internal dependency graph, enabling tsc --build to compile only packages that have changed since the last build, with results cached to disk. Teams that have configured project references correctly see TypeScript build times in large monorepos drop from minutes to seconds for incremental compilations. The configuration cost is non-trivial — it requires explicit composite settings, references arrays in each tsconfig.json, and discipline about the boundaries between packages — but for codebases above a certain size it is the difference between a workable and an unworkable TypeScript setup.
The packages that handle this best — Nx, Turborepo, and similar monorepo orchestrators — take project references further by providing caching at the CI level, sharing computed type declarations across build environments. For npm package authors shipping monorepos, the choice between project references and build-tool-level type stripping is one of the most consequential TypeScript infrastructure decisions they will make.
Migration Costs vs. Payoff: The Real Calculus for Codebase Adoption
The "TypeScript adds complexity" objection almost always comes from developers who have encountered TypeScript's friction without experiencing its payoff — which only materializes at a scale and over a time horizon that exceeds most tutorial examples. The honest framing of the adoption decision is not "is TypeScript worth the complexity?" but "is TypeScript worth the upfront migration cost, given my project's expected longevity and team size?"
For a solo project expected to live for six months, the answer can legitimately be no. The time investment in configuring tsconfig.json, fixing initial type errors during migration, and getting the team aligned on strict-versus-permissive settings may exceed the bugs prevented during that window. This is not a failure of TypeScript's value proposition — it is a rational time-horizon calculation. The payoff from catching type errors compounds over time; the migration cost is paid once at the start.
For any codebase maintained beyond a year with more than one developer, the calculus reverses decisively. Refactoring a JavaScript codebase without TypeScript requires comprehensive test coverage as a substitute for compiler verification, and tests can only verify behaviors the test author anticipated. TypeScript's compiler verifies structural correctness across the entire codebase on every save, catching the class of errors that tests miss: calling a function with the wrong argument type, accessing a property that may be undefined, passing an object that is missing a required field. A large codebase that has been through three engineers and two years of feature additions accumulates enough type assumption drift that TypeScript's first strict-mode run routinely surfaces hundreds of latent bugs. The conversion cost is high precisely because the accumulated technical debt was real.
The migration cost itself has dropped substantially since 2020. TypeScript's allowJs flag allows gradual adoption — you can rename files from .js to .ts one at a time, fixing type errors file by file, without converting the entire codebase at once. The @ts-check directive enables type checking in .js files via JSDoc comments without a TypeScript build step. The practical path from a mature JavaScript codebase to strict TypeScript is now well-documented and incrementally executable, which changes the migration calculation for teams that previously felt the cost was prohibitive.
What the Long-Tail Gap Reveals About npm Economics
The gap between 95% TypeScript adoption among the top 100 packages and 42% adoption across all two million npm packages is not primarily a quality gap — it is an economics gap. Maintaining high-quality TypeScript types is ongoing work. Every time a package changes its public API, the type declarations must be updated to match. For packages with dedicated maintainers or corporate backing, this cost is absorbed into the existing maintenance workflow. For the long-tail packages authored by solo developers in evenings and weekends, it is an additional tax on releases that reduces maintenance sustainability.
The DefinitelyTyped workflow exists to offload this tax. Rather than requiring the package author to maintain types, it allows the community to maintain them independently. The economics work for packages with enough users that community contributors materialize — @types/express, @types/node, and @types/lodash all have active contributors because millions of developers depend on them and motivated TypeScript users will contribute rather than lose types. For packages with ten thousand weekly downloads and no TypeScript contributors who use them, DefinitelyTyped types either never appear or appear once and go stale.
The 42% long-tail adoption number will grow, but slowly and through two mechanisms. First, newer packages are being authored in TypeScript from the start at a much higher rate than older ones — the composition of the long tail shifts toward TypeScript every year as old packages lose relevance and new ones are added. Second, tools like dts-gen and typescript-definition-generator make it easier to produce initial type declarations automatically, lowering the marginal cost of adding types to an existing JavaScript package. Neither mechanism moves fast because the long tail is enormous and self-propagating: the category of small, rarely-updated JavaScript packages grows at the same rate that TypeScript-first packages at the top capture mindshare from it.
Compare TypeScript support and package health at PkgPulse.
Compare Typescript and Jsdoc package health on PkgPulse.
See also: AVA vs Jest and Packages That Ship TypeScript Types vs DefinitelyTyped, Most Depended-On npm Packages (And Their Alternatives).
See the live comparison
View typescript vs. jsdoc on PkgPulse →