为什么 TypeScript 是 CLI 工具的理想语言?
\n如果你用 Python 编程,突然想创建一个控制台工具,很可能你的第一反应是使用 argparse 或 click。这很合理。但如果我告诉你,在 CLI 领域,TypeScript 可以胜过任何 Python 工具呢?是的,你没听错。
TypeScript 不仅仅是“带类型的 JavaScript”。它是一种将 CLI 工具开发变成可预测且安全过程的语言。不再有“为什么我得到的是 undefined 而不是字符串?”或者“我传了一个数字,它却变成了字符串”这样的问题。强类型在编译阶段就消除了整类错误。
但最大的优势是生态系统。Node.js 允许你在任何地方运行 TypeScript 代码:服务器、Docker、Raspberry Pi。而 npm 让发布工具变得只需五分钟。今天我们将走完整个过程:从一个空文件夹到一个完整的 CLI 工具,可以用 npm install -g 命令安装。
我们要构建什么?
\n想象一下:你经常处理 JSON 文件,需要快速统计字段数量、验证有效性或转换为 CSV。我们将编写一个名为 json-toolkit 的工具,它可以做三件事:
- \n
- validate — 验证 JSON 是否有效; \n
- count — 统计顶层键的数量; \n
- to-csv — 将对象数组转换为 CSV。 \n
听起来很简单?是的。但通过这个例子,你将掌握所有关键技巧:参数处理、文件系统操作、终端颜色和错误处理。
\n\n步骤 1. 项目设置
\n首先创建一个文件夹并初始化项目:
\nmkdir json-toolkit\ncd json-toolkit\nnpm init -y\n现在安装 TypeScript 和必要的包:
\nnpm install -D typescript @types/node\nnpm install commander chalk\n- \n
commander— 用于解析命令行参数的库(类似于 Python 的 argparse,但更方便); \n chalk— 为终端输出添加颜色; \n @types/node— Node.js 的类型定义。 \n
创建 tsconfig.json:
{\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注意:outDir 是代码编译到的文件夹,而 rootDir 是源代码文件夹。这是 TypeScript 项目的标准做法。
步骤 2. 编写工具核心
\n创建 src 文件夹和文件 src/index.ts。我们从导入和配置 commander 开始:
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('用于处理 JSON 文件的工具')\n .version('1.0.0');\n\nprogram\n .command('validate')\n .argument('<file>', 'JSON 文件路径')\n .description('验证 JSON 是否有效')\n .action((file: string) => {\n try {\n const content = readFileSync(file, 'utf-8');\n JSON.parse(content);\n console.log(chalk.green('✓ JSON 有效!'));\n } catch (err) {\n console.error(chalk.red('✗ 错误:'), (err as Error).message);\n }\n });\n\nprogram\n .command('count')\n .argument('<file>', 'JSON 文件路径')\n .description('统计顶层键的数量')\n .action((file: string) => {\n if (!existsSync(file)) {\n console.error(chalk.red('文件未找到!'));\n return;\n }\n const content = readFileSync(file, 'utf-8');\n const data = JSON.parse(content);\n const keys = Object