December 6th, 2019 - 8 min read
We're creating a Node.js setup with Typescript compiler (short TSC) from scratch, so you can use Typescript for your next Node.js app.
I'll guide you through each step from start to finish so you can start with your app development.
We're not creating any demo app as I want to focus on the setup of the project.
The setup will contain:
I'm using Yarn here but if you prefer Npm that's also OK. Just replace everything with Npm commands npm install ...
or npm run ...
.
I'm using Yarn because I think there are still some benefits that Npm doesn't offer. Just to mention some:
add
vs install
and to execute commands with-out run
.So both are OK to use, the only thing I recommend is stick to either Yarn or Npm in your team and don't mix them as having both lock files is a problem.
Run mkdir my-node-app && cd my-node-app
and yarn init -y
. Next, install the dependencies with yarn add nodemon typescript @types/node ts-node eslint eslint-config-prettier prettier rimraf @typescript-eslint/parser @typescript-eslint/eslint-plugin -DE
this will add the following packages as development dependencies to your project:
tsc
./lib
in a cross-platform mannerThe last part -DE
in the command means to install these as dev. dependencies and pin the version with -E, --exact
option. More about version pinning can be found in this post.
Create a Typescript config file with node_modules\.bin\tsc --init
(or tsc --init
if you have Typescript installed globally). This will add a tsconfig.json
file to your project. Now, we need to modify the file a bit for our setup:
outDir: './lib'
- line 15 - Output folder of the generated coderootDir: './src'
- line 16 - This is the folder where Typescript will look for source files"resolveJsonModule": true
- Add that to your configuration to enable typed JSON imports."esModuleInterop": true
- Already configured and needed so that CommonJs imports are compatible with ES6 modules. More details about it, in this SO question."module": "commonjs"
- This allows us to define the output module type. commonjs
is the standard module format used in Node.js, therefore this is what we will adhere to.Create a .eslintrc.js
in the project root with the content:
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
env: {
browser: true,
amd: true,
node: true
}
};
Enable linting in your project with VS Code settings.json
as mentioned in the VS code setup post and also add ESLint action on save in the settings.json
:
{
// ... other config ...,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
Now it will automatically format your code on save with Prettier and Eslint.
For development, we're adding the Nodemon configuration to a nodemon.json
to the project root (as that's easier than passing everything as a command-line argument):
{
"watch": ["src"],
"ext": "ts",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node ./src/index.ts"
}
Next, we'll add our start & build scripts to the package.json
:
{
// other content of package.json
"scripts": {
"start": "nodemon",
"build": "tsc -p .",
"clean": "rimraf lib",
"prebuild": "yarn clean"
}
}
yarn start
is used for development and that's starting Typescript and finally runs Node.js with your index script. Nodemon is also watching your source code and automatically re-runs TSC to update your code.
Run git init
and create a .gitignore
file:
# Log files
*.log
# Ignore our build files
lib
# Ignore node dependencies
node_modules
You can test if your ignore file is right by running git status
and keep in mind that you don't want to commit any generated files or log messages.
Add the index.ts
to src/
folder:
function greeter(message: string): void {
console.log(message);
}
greeter("Yay! This works!");
Run yarn start
and you should see the greeting Yay! This works!
in the console.
To build your project run yarn build
. Once build finished, you can test your app with node ./lib
You can try if Typescript is doing it's job by changing the string 'Yay! This works!'
to a number. TSlint will mark the type error and in the console you'll also get it as a message.
Other test runner frameworks would also work (e.g. Mocha, Jasmine, Karma, Ava, etc.) but I'll use Jest as it will fully support Typescript.
Run yarn add jest ts-jest @types/jest -DE
to add it.
To the project root, add the jest.config.js
file:
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.json",
},
},
moduleFileExtensions: ["ts", "js"],
transform: {
"^.+\\.(ts|tsx)$": "ts-jest",
},
testMatch: ["**/test/**/*.test.(ts|js)"],
testEnvironment: "node",
};
This config is telling ts-jest
which TS config to use and that our test files are in test
folder. The transform is used so Jest knows that we'd like to use TS-Jest preprocessor for our files with .ts
extension.
We can add "test": "jest"
to our scripts in package.json
, so we can run yarn test
to start our tests.
Add a file called hello.test.ts
to the folder ./src
:
describe('My module to test', () => {
it('should pass', () => {
expect(true).toBeTruthy();
});
});
Now, run your first test with yarn test
and you will get one passing test. It's not testing anything but you should get an idea.
If you're new to Jest, I'd recommend having a look at the Jest getting started guide.
To learn about Typescript I would start with the Typescript in 5 Minutes guide.
If you're looking for type definitions, I'd recommend the TypeSearch page from Microsoft. Just enter the package where you need types and the search result will redirect you to the Npm.js page of that package.
You could also search directly on Npm.js by looking for @types/...
packages.
Your setup is ready for your next Node.js project. You can create a Web server, a JSON API server or a command-line interface (CLI) tool and a lot more...
A web or API server could be created with express.js and a CLI with Commander.js.
For a CLI tool, you could also checkout oclif but with it, you don't need the setup mentioned above as it includes a generator for your project. So I would probably start with Commander.js as you're already having everything in place (if you followed this guide).
I'll write a post about a CLI that I'm creating. It's a license selection tool for a project. So you can run choosealicense add mit
. It will generate a LICENSE
file and add the license
key to your package.json
. I know that similar tools are available but I want to create it to learn how to create a CLI and to have every feature as I want it.
If you're building somthing with Node.js, please let me know what you're building. I'm always interested in new ideas. You can add a comment here or drop me a line on Twitter.
You can find the source code in the following Github repository.
Good luck & Happy Coding!
I read in a post that Tslint will be deprecated in favor of typescript-eslint.
I don't know if Typescript-eslint tooling (VS code extension + ts-eslint) is ready but I'll check it and write about my experience once I've tested it.
OK, I've updated this post to use ESlint instead of TSlint as TSlint in now deprecated.