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):
- the
npm run build
command used to betsc --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. - the
tsconfig.json
file used to not includerootDir
. It does now, for even more clarity. - the
npm test
command used to not include theTS_NODE_PROJECT=src/tsconfig.json
part. It is now, becausets-node/register
actually needs that to know which lib the tsconfig project file tells it to expect (kudos to this SO answer). - pro-tip: did you know running
tsc --init
will create a defaulttsconfig.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.