CLI utilities in TypeScript: from idea to ready-made tool in an hour

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why TypeScript is the ideal language for CLI utilities?

\n

If you write in Python and suddenly think about creating a console utility, most likely your first impulse is to use argparse or click. And that makes sense. But what if I tell you that TypeScript can outshine any Python tool in the CLI world? Yes, you heard that right.

\n

TypeScript is not just "JavaScript with types". It is a language that turns CLI utility development into a predictable and safe process. No more "why do I have undefined instead of a string?" or "I passed a number, but it became a string". Strong typing eliminates a whole class of errors at the compilation stage.

\n

But the main advantage is the ecosystem. Node.js allows you to run TypeScript code anywhere: on a server, in Docker, on a Raspberry Pi. And npm makes publishing a utility a five-minute task. Today we will go through the entire path: from an empty folder to a ready-made CLI utility that can be installed with the npm install -g command.

\n\n

What are we going to build?

\n

Imagine: you often work with JSON files and need to quickly count the number of fields, check validity, or convert to CSV. We will write a json-toolkit utility that does three things:

\n
    \n
  • validate — checks JSON for validity;
  • \n
  • count — counts the number of top-level keys;
  • \n
  • to-csv — converts an array of objects to CSV.
  • \n
\n

Sounds simple? Yes. But with this example, you will master all the key techniques: argument handling, file system operations, terminal colors, and error handling.

\n\n

Step 1. Project setup

\n

First, create a folder and initialize the project:

\n
mkdir json-toolkit\ncd json-toolkit\nnpm init -y
\n

Now install TypeScript and the necessary packages:

\n
npm install -D typescript @types/node\nnpm install commander chalk
\n
    \n
  • commander — a library for parsing command line arguments (similar to Python's argparse, but more convenient);
  • \n
  • chalk — colors the terminal output;
  • \n
  • @types/node — types for Node.js.
  • \n
\n

Create tsconfig.json:

\n
{\n  "compilerOptions": {\n    "target": "ES2020",\n    "module": "commonjs",\n    "outDir": "./dist",\n    "rootDir": "./src",\n    "strict": true,\n    "esModuleInterop": true,\n    "declaration": true\n  },\n  "include": ["src/**/*"]\n}
\n

Note: outDir is the folder where the code will be compiled, and rootDir is the source code. This is standard practice for TypeScript projects.

\n\n

Step 2. Writing the utility core

\n

Create the src folder and the file src/index.ts. Let's start with imports and commander setup:

\n
import { Command } from 'commander';\nimport { readFileSync, existsSync } from 'fs';\nimport chalk from 'chalk';\n\nconst program = new Command();\n\nprogram\n  .name('json-toolkit')\n  .description('Utility for working with JSON files')\n  .version('1.0.0');\n\nprogram\n  .command('validate')\n  .argument('<file>', 'path to JSON file')\n  .description('Check JSON validity')\n  .action((file: string) => {\n    try {\n      const content = readFileSync(file, 'utf-8');\n      JSON.parse(content);\n      console.log(chalk.green('✓ JSON is valid!'));\n    } catch (err) {\n      console.error(chalk.red('✗ Error:'), (err as Error).message);\n    }\n  });\n\nprogram\n  .command('count')\n  .argument('<file>', 'path to JSON file')\n  .description('Count the number of top-level keys')\n  .action((file: string) => {\n    if (!existsSync(file)) {\n      console.error(chalk.red('File not found!'));\n      return;\n    }\n    const content = readFileSync(file, 'utf-8');\n    const data = JSON.parse(content);\n    const keys = Object                

Blogs

Book Recommendations