Vite’s TypeScript integration isn’t just about compile-time checks; it’s designed to let your code run with zero JavaScript transpilation overhead during development.

Let’s see Vite and TypeScript in action.

Imagine a simple Vite project with a TypeScript file:

src/main.ts:

import './style.css'

document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
  <h1>Vite + TS</h1>
  <p>${message}</p>
`

And a tsconfig.json:

tsconfig.json:

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "View",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "lib": ["ESNext", "DOM"]
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

When you run npm run dev, Vite doesn’t wait for tsc to finish. It uses esbuild under the hood for lightning-fast transpilation to compatible JavaScript. TypeScript’s type checking happens in parallel, often in a separate process, ensuring your development server remains snappy. The tsconfig.json guides both esbuild’s transformation and the parallel type checker.

The problem Vite solves here is the common bottleneck in many frontend build tools: the time it takes for the TypeScript compiler (tsc) to transpile TS to JS. tsc is powerful but can be slow on large projects. Vite, by default, uses esbuild, which is written in Go and is orders of magnitude faster for this specific task. However, this speed comes with a slight trade-off: esbuild’s TypeScript support isn’t 100% feature-complete compared to tsc. For features like decorators or certain advanced type system features, you might still need tsc.

Vite’s tsconfig.json configuration is crucial. The compilerOptions here are mostly passed to esbuild for transpilation, with a few exceptions where Vite might do its own processing or rely on tsc for specific checks.

  • target: Determines the ECMAScript version the code will be transpiled to. ESNext is common for modern browsers.
  • useDefineForClassFields: Essential for correct class field transpilation with modern JavaScript.
  • module: Specifies the module system. ESNext aligns with native browser modules.
  • moduleResolution: How module paths are resolved. Node is standard.
  • strict: Enables all strict type-checking options. Highly recommended.
  • jsx: How JSX is handled. View is Vite’s default for React/Preact.
  • lib: Specifies built-in TypeScript libraries to include. ESNext and DOM are typical for web development.

The include and exclude fields in tsconfig.json tell tsc (when it’s invoked for type checking) which files to process. Vite itself also respects these patterns for its internal processing.

In a typical Vite setup, tsc is still used for actual type checking, but it’s often run in a way that doesn’t block the development server. You might see tsc --noEmit --watch running in a separate terminal, or Vite might integrate with it more deeply. The --noEmit flag is key here; it tells tsc not to generate JavaScript files, as esbuild is already handling that. It only performs type checking.

The references field in tsconfig.json is interesting. It allows for project references, enabling faster incremental builds by breaking a large project into smaller, independently compilable parts. tsconfig.node.json is often used to configure TypeScript for the Node.js environment that Vite runs in, separate from your application’s client-side code.

When you encounter type errors during development, Vite will display them directly in the browser overlay. These errors originate from the parallel type-checking process. If you’re seeing incorrect type behavior or unexpected JavaScript output, double-check your tsconfig.json. A common mistake is forgetting to include lib: ["ESNext", "DOM"] if you’re using modern JavaScript features or DOM APIs, which can lead to undefined errors for global objects.

The skipLibCheck: true option is a performance optimization that tells the TypeScript compiler to skip type checking of declaration files (.d.ts). While it speeds things up, it can mask certain type-related issues that might arise from third-party libraries, so use it with caution if you suspect library-specific problems.

The true power of Vite’s TypeScript integration lies in its ability to leverage esbuild for blazing-fast development builds while still providing robust, tsc-backed type checking. This hybrid approach ensures a smooth developer experience without sacrificing code quality.

The next thing you’ll likely grapple with is optimizing your tsconfig.json for monorepos or complex project structures using project references.

Want structured learning?

Take the full Vite course →