Project: Type-Safe CLI Todo Tool
Introduction
This project builds a command-line todo app in TypeScript: typed models, parsed commands, JSON file persistence, and clear error messages. You practice Node + tsc (or tsx) workflows from the integration chapters in one small tool you can extend later.
Prerequisites
Project Goals
- Define
Todoand status types - Parse subcommands:
add,list,done,remove - Persist todos in
todos.json - Exit with non-zero code on user errors
Folder Setup
bash
mkdir ts-todo-cli
cd ts-todo-cli
npm init -y
npm install --save-dev typescript @types/node tsxtext
ts-todo-cli/
├── package.json
├── tsconfig.json
└── src/
├── index.ts
├── types.ts
├── store.ts
└── commands.tstsconfig.json:
json
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true
},
"include": ["src/**/*"]
}package.json scripts:
json
{
"type": "module",
"bin": { "todos": "./dist/index.js" },
"scripts": {
"build": "tsc",
"dev": "tsx src/index.ts",
"start": "node dist/index.js"
}
}Step 1: Domain Types
src/types.ts:
typescript
Code explanation:
TodoStatusis a string union—invalid statuses fail at compile timeCommandis a discriminated union keyed byname
Step 2: File Store
src/store.ts:
typescript
Step 3: Commands
src/commands.ts:
typescript
Step 4: CLI Entry
src/index.ts:
typescript
Try It
bash
npm run dev -- add "Learn TypeScript"
npm run dev -- list
npm run dev -- done <id-from-list>
npm run build
npm start -- listExtensions (Optional)
- Add
editcommand withPartial<Pick<Todo, "title" | "status">> - Validate duplicate titles
- Publish to npm with
binfield andfiles: ["dist"]
FAQ
Why validate JSON with isTodo?
Runtime data from disk is untrusted even on your machine.
Use a CLI library?
commander or yargs add typed options—good next step after manual parsing.
Zod for parsing?
Popular for runtime schemas—pairs well with unknown at boundaries.