minimal TypeScript project setup

As a fan of code-minimalism (at least a wannabe), I always try to use the smallest setup necessary just enough to build something. As someone who’ve been working with JavaScript since before jQuery time, I understand how easy it is for a JavaScript-based project to get bloated with libraries, config files, and framework boilerplate setups. In this post, I’d love to discuss a setup that’s minimal enough for me to start a TypeScript-based project.

First, let’s take a look at the project structure (which is also available at this Github repo):

project-root
|_ package.json
|_ src
|_ tsconfig.json
|_ index.ts (or whatever name you want for your main file)
|_ test
|_ dist (to be gitignored)

Now, let’s take a look at the package.json file (please note that the command arguments should explain themselves, but if there’s anything unclear to you, please feel free to ask up in the comment section):

...,
"scripts": {
"dev": "ts-node --project src/tsconfig.json src/index.ts",
"start": "node dist/index.js",
"build": "tsc -p src/tsconfig.json",
"test": "TS_NODE_PROJECT=src/tsconfig.json mocha -r ts-node/register test/*.spec.ts",
"pretest": "npm run build",
"postinstall": "npm run build"
},
"dependencies": {
"@types/mocha": "^5.2.5",
"mocha": "^5.2.0",
"ts-node": "^7.0.1",
"typescript": "^3.1.6"
},
...

And then, the src/tsconfig.json file:

{
"compilerOptions": {
"target": "ES5", // obviously, use whatever value you need
"lib": ["ES2015"], // obviously, use whatever value(s) you need
"outDir": "../dist",
"rootDir": "."
}
}

If I want to go even more minimal, I could ditch ts-node and run tsc every time I need to run or test my build. But so far I’m happy with running and testing my .ts files directly.

I could use nodemon or ts-node-dev to take care of auto-reloading, but it’s beyond the scope of this post.

I could organize my test files in a totally different way (i.e. mix *.spec.ts with the .ts files under src themselves) – then I’ll just need to edit the target pattern of my mocha command). For this example, I’m happy to have my test files under their own directory.

The main point is that this setup allows me to write in TypeScript, then compile into JavaScript, using the minimum amount of external libraries.

PS: I could argue that I won’t even need @types/mocha. For this example, my text editor (Atom) wanted it, so I pleased it, but your mileage might vary.

PPS: you may also ask why those things are in my dependencies (and not devDependencies), which is a valid question. For me, if I want to run tests and compile on the (production/build) server, I’ll list them as my main dependencies.

EDITS (Jan 20th, 2019):

  1. the npm run build command used to be tsc --build ... but the --build flag has now been dropped as it’s not really needed. Specifying a project file (tsconfig.json) is much clearer. Please feel free to consult the tsc compiler references if you’re still curious about stuff.
  2. the tsconfig.json file used to not include rootDir. It does now, for even more clarity.
  3. the npm test command used to not include the TS_NODE_PROJECT=src/tsconfig.json part. It is now, because ts-node/register actually needs that to know which lib the tsconfig project file tells it to expect (kudos to this SO answer).
  4. pro-tip: did you know running tsc --init will create a default tsconfig.json file with verbose options (but mostly commented out for a bare minimal start) so you can tinker with? Do give it a try, you’ll love it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s