vue-tsc

A command-line type-checking tool that teaches the TypeScript compiler to understand Vue single-file components.

Tool
npm
v3.3.13
6,735 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
90 /100 Excellent
Development Activity 100
Maintenance 96
Community 64
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
69 /100 Good
Architecture 82
Code Quality 85
Innovation 85
Learning Curve 25

vue-tsc is the command-line type checker for Vue projects, published as one package inside the vuejs/language-tools monorepo alongside the editor tooling that powers the official Vue VS Code extension. It wraps tsc itself rather than reimplementing it: it hands TypeScript a Vue-aware language plugin (built on @vue/language-core) so .vue files are transformed into virtual TypeScript code before the compiler ever sees them, then delegates everything else — argument parsing, diagnostics, declaration emit — to the real tsc binary.

Because it is a thin wrapper, every native tsc flag works unchanged: vue-tsc --noEmit type-checks a project the same way tsc --noEmit would if .vue files were plain TypeScript, and vue-tsc --declaration --emitDeclarationOnly produces .d.ts files for a Vue component library. It reads vueCompilerOptions straight out of the project’s existing tsconfig.json, so there is no separate configuration format to learn, and it automatically detects related file types (Vitepress or petite-vue extensions) declared in that config.

vue-tsc is the standard type-check step wired into nearly every Vue 3 + TypeScript project scaffold, run in CI to catch template and script type errors that a bundler’s transpile-only pipeline would silently let through.

What You Get

  • Drop-in tsc replacement - accepts the exact same CLI flags as tsc, so existing type-check npm scripts just swap the binary name.
  • Template type checking - type errors inside <template> blocks (wrong prop names, mistyped v-model bindings, bad event handler signatures) are reported alongside <script> errors.
  • Declaration file generation - --declaration --emitDeclarationOnly emits .d.ts files for publishable Vue component libraries.
  • Zero extra config format - reads vueCompilerOptions from the project’s existing tsconfig.json instead of introducing a new config file.
  • Programmatic run() API - importable for tooling that needs to point at a custom TypeScript installation rather than the one on PATH.

Common Use Cases

  • CI type-check gate - a type-check script (vue-tsc --noEmit) run in GitHub Actions/CI to fail a build when a .vue file has a type error a bundler would otherwise ignore.
  • Publishing typed component libraries - authors of shared Vue component packages use vue-tsc --declaration --emitDeclarationOnly to ship accurate .d.ts files to consumers.
  • Pre-commit / pre-push hooks - projects wire vue-tsc --noEmit into Husky or lint-staged so type errors are caught before code reaches a PR.
  • Editor-independent verification - teams that don’t all use VS Code + Volar still get the same type information enforced from the command line, keeping local and CI results consistent.

Under The Hood

Architecture

vue-tsc (packages/tsc in the vuejs/language-tools monorepo) is a thin CLI wrapper — a single index.ts plus a bin/vue-tsc.js shim — around @volar/typescript’s runTsc, into which it injects a Vue language plugin constructed from @vue/language-core (createVueLanguagePlugin) so that .vue single-file components are transformed into virtual TypeScript code the real compiler can consume; a small retry loop catches a sentinel retryToken error to progressively discover which file extensions (.vue, plus optional Vitepress/petite-vue extensions) a project actually uses before settling on a final compiler run, and a resolveTscPath helper handles resolving the correct tsc binary even when TypeScript is aliased to an alternate package. Almost all of the substantive logic — SFC parsing, virtual code generation, type inference across template and script boundaries — lives in the sibling @vue/language-core package that vue-tsc depends on as workspace:*, making vue-tsc itself a deliberately thin, low-risk integration point in a larger, well-separated monorepo (language-core, language-server, language-service, typescript-plugin, component-meta all sit alongside it).

Tech Stack

Written entirely in TypeScript within a pnpm workspace monorepo (managed with lerna for versioning), vue-tsc depends on @volar/typescript for the generic Volar.js language-tooling bridge and @vue/language-core for Vue-specific compilation, and peer-depends on typescript (>=5.0.0) to supply the actual compiler it wraps; the monorepo builds via TypeScript project references (tsc -b), is formatted with dprint rather than Prettier, linted with @tsslint (a TypeScript-native lint runner, with an ESLint compatibility layer), tested with Vitest, and runs its full suite through GitHub Actions on every push and pull request.

Code Quality

The package has a dedicated tests/ directory (build.spec.ts, dts.spec.ts, typecheck.spec.ts, unmapped-diagnostics.spec.ts) built on Vitest inline snapshots, driven against a large shared test-workspace/tsc fixture directory containing dozens of numbered regression cases tied to specific historical GitHub issues, which reflects a strong regression-testing discipline; the source itself uses a deliberate sentinel-exception pattern for its extension-discovery retry loop rather than swallowing failures, is fully typed with no loose any surface, and the whole monorepo is enforced by tsslint with an automated lint/format-fix CI job on every push.

API Design The public surface is intentionally minimal: the CLI accepts every native tsc flag unchanged, so teams migrating from tsc to vue-tsc change one binary name and nothing else; Vue-specific behavior is configured through the vueCompilerOptions block already present in tsconfig.json rather than a new file format, and the only additional API is a single optional run(tscPath?) export for tooling that needs to target a non-default TypeScript install. This keeps day-one adoption to essentially zero new concepts, at the cost of the extension-discovery retry mechanism being entirely invisible (and undocumented) to end users.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers