Creating a CLI with TypeScript

February 17, 2019

Photo by Anders Jildén

Recently, I shared typed-scss-modules, a command-line interface (CLI) for generating type definitions for CSS Modules using SASS. I’ve used many npm packages that provide executable commands, such as tsc from TypeScript, or apollo for Apollo GraphQL tooling, but have never created a package with an executable.

Considering typed-scss-modules is a tool for generating TypeScript type definitions, it seemed fit to also be written in TypeScript. But where to start?

📦 Getting Started

After searching around and also digging through various packages that offered executables the packages below were the most helpful when creating a TypeScript command-line npm package.

Core Tooling

Some of this tooling is specific to TypeScript, but the majority of this is useful for any npm package that includes an executable for doing things like creating the CLI options or printing formatted output.

  • ts-node: TypeScript Node is used to execute TypeScript. This is useful in development to run the CLI without needing to build anything. Adding a custom script to package.json with the same name will enable executing the script the similarily during development and in the published version. For example, adding "my-script": "ts-node ./lib/cli.ts" to the package.json scripts property will running it with yarn my-script or npm run my-script.

  • yargs: Yargs helps build interactive command line tools, by parsing arguments and generating a user interface. There are also other packages like commander.js that can be used for this as well. On an unrelated note, the type definitions for yargs (@types/yargs) are impressive. They allow chaining methods that build up a final object with all of the CLI options with the proper types.

  • chalk: Chalk provides terminal string styling to display messages in different ways depending on the context. The gif below is an example of using typed-scss-modules and the output, which is styled using chalk. If looking to create a more complex CLI, consider giving ink a try. It also may be a better fit for typed-scss-modules to show the total number of type definitions generated, rather than a full list of every file which could get lengthy in larger projects.