Todo App with TypeScript
In this page:
Core Concept
A typed todo app is a common first TypeScript project because its data model is small (an id, a text string, a completed flag) but still demonstrates end-to-end typing: typed state, typed props, and typed event handlers all in one place.
Example: Core Concept
interface Todo {
id: string;
text: string;
completed: boolean;
}
const todo: Todo = { id: "1", text: "Buy milk", completed: false };
console.log(todo);
Basic Setup
A basic setup defines an interface Todo { id: string; text: string; completed: boolean } and a typed array Todo[] as the app's central piece of state, whether managed with useState, a class field, or a store.
Example: Basic Setup
interface Todo {
id: string;
text: string;
completed: boolean;
}
const todos: Todo[] = [];
console.log(todos.length);
Typed Example
A typed example: function addTodo(text: string): Todo { return { id: crypto.randomUUID(), text, completed: false } } guarantees every new todo object always has the exact right shape, with no missing fields possible.
Example: Typed Example
interface Todo {
id: string;
text: string;
completed: boolean;
}
function addTodo(text: string): Todo {
return { id: String(Date.now()), text, completed: false };
}
console.log(addTodo("Write code"));
Project Usage
In a real project, this same Todo interface gets reused across the add form, the list-rendering component, and the toggle/delete handlers, so a change to the todo shape (like adding a priority field) is caught everywhere it's used, not just where it's defined.
Example: Project Usage
interface Todo {
id: string;
text: string;
completed: boolean;
}
function toggleTodo(todos: Todo[], id: string): Todo[] {
return todos.map((t) => (t.id === id ? { ...t, completed: !t.completed } : t));
}
console.log(toggleTodo([{ id: "1", text: "Task", completed: false }], "1"));
Best Practices
Keep the Todo type in its own small module imported everywhere it's needed, rather than redefining an inline {id, text, completed} object type separately in each component that touches it.
Example: Best Practices
// todo.ts (its own small module)
export interface Todo {
id: string;
text: string;
completed: boolean;
}
console.log("Todo interface imported everywhere it's needed, defined once");
Chapter Quiz — Complete all 14 topics to unlock
0/14 topics done
Complete these topics first:
- Todo App with TypeScript
- REST API with Express + TypeScript
- React Dashboard with TypeScript
- CLI Tool with TypeScript
- Library with TypeScript
- Full Stack TypeScript App
- TypeScript Design System
- TypeScript Monorepo Project
- Authentication System
- Real-time App with Socket.io
- GraphQL API with TypeScript
- Microservices with TypeScript
- TypeScript Best Practices Review
- What to Learn Next