TypeScript with Vite and Frontend Apps
Introduction
Modern frontends use Vite (or similar tools) for fast dev servers and production bundles. TypeScript type-checks your code—often via tsc while Vite transpiles. This chapter walks through a React + TypeScript Vite app and explains how responsibilities split between tools.
Prerequisites
Scaffold a Project
npm create vite@latest my-app -- --template react-ts
cd my-app
npm installTypical layout:
my-app/
├── index.html
├── package.json
├── tsconfig.json
├── tsconfig.app.json
├── vite.config.ts
└── src/
├── main.tsx
├── App.tsx
└── vite-env.d.tsnpm run dev starts Vite. npm run build usually runs tsc -b then vite build.
Who Does What?
| Task | Tool |
|---|---|
| Dev server, HMR | Vite |
| TS → JS in dev | esbuild (via Vite) |
| Production bundle | Rollup (via Vite) |
| Full type-check | tsc (noEmit: true) |
Vite transpiles quickly; run tsc in CI to catch type errors Vite might skip.
tsconfig.app.json (Typical)
Path Aliases
vite.config.ts:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import path from "node:path";
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
});tsconfig.app.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}Vite and TypeScript aliases must match.
Typed Component Example
src/components/Button.tsx:
type ButtonProps = {
label: string;
onClick: () => void;
};
export function Button({ label, onClick }: ButtonProps) {
return (
<button type="button" onClick={onClick}>
{label}
</button>
);
}Environment Variables
src/vite-env.d.ts:
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}Only variables prefixed with VITE_ are exposed to client code.
Scripts
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"typecheck": "tsc -b --noEmit"
}
}Vanilla TypeScript Template
npm create vite@latest my-vanilla-app -- --template vanilla-tsSame pattern: Vite bundles; tsc checks types.
FAQ
Why is dev so fast?
esbuild strips types without full program analysis. tsc runs separately.
Use tsc to build the SPA?
Use vite build for JS; tsc for type-checking (and .d.ts only for libraries).
Vue or Svelte?
Use vue-ts or svelte-ts templates—same noEmit + bundler split. For Vue 3 + defineProps + vue-tsc, see the Vue track chapter 18 and chapter 02.
ESLint?
Add @typescript-eslint and run alongside tsc in CI.