Project: Type-Safe Frontend App (Vite)

Introduction

This project builds a small Vite + TypeScript app that fetches typed API data and updates the DOM safely. You practice frontend tsconfig, import.meta.env, modeling API responses, and separating UI modules—without a heavy framework.

Prerequisites

Project Goals

  • Load users from a public JSON API (or mock)
  • Render a list with loading and error states
  • Use discriminated union for UI state
  • Type form input handling

Setup

bash
npm create vite@latest ts-users-app -- --template vanilla-ts
cd ts-users-app
npm install
text
src/
├── main.ts
├── api.ts
├── types.ts
├── ui.ts
└── style.css

API Types

src/types.ts:

typescript
export interface User {
  id: number;
  name: string;
  email: string;
}
 
export type LoadState<T> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; message: string };

Fetch Layer

src/api.ts:

.env:

text
VITE_API_URL=https://jsonplaceholder.typicode.com

UI Module

src/ui.ts:

Main Entry

src/main.ts:

Run

bash
npm run dev
npm run build

npm run build runs tsc then Vite—fix any type errors before shipping.

Extensions

  • Add search input with typed debounce helper
  • Migrate to React and move LoadState to a hook
  • Connect to your REST API from the API project chapter

FAQ

Why vanilla instead of React?

Focuses on types and DOM without JSX. React template is one command away.

CORS errors?

Use Vite server.proxy in vite.config.ts for local APIs.

Stricter env types?

Extend ImportMetaEnv in vite-env.d.ts.