"TypeScript is the Robin to your Batman in the world of JavaScript programming. It's a powerful sidekick that helps you write better code with fewer errors.”
Just like a superhero gains their abilities through a unique process, setting up Node with Express and TypeScript can give you powerful tools to build robust web applications. With Node.js and Express, you can easily create web applications and APIs, and when you add TypeScript to the mix, you gain strong typing and better error checking. Ready to become a web development superhero? Let's dive in!
Let's start our journey by initializing a project, which is where the battle will begin. As any superhero knows, preparation is key to success. So, we'll cast the following spell to make a folder and initialize it with default settings using yarn
:
mkdir express_ts_setup && cd express_ts_setup
yarn init -y
We've successfully initialized our project and let’s add some more friends to our side. Like any good detective in a bat suit , we must be prepared for battle.
Our first challenge is the introverted Node engine. It may seem harmless, but it's a powerful force that can cause chaos if left unchecked. That's why we need to call on the help of our friends and their allies.
We'll invite express
and typescript
to join our superhero squad, but we must also call @types/node
, and @types/express
so typescript
will understand our node engine
and express
It's like calling on your superhero friends to fight a villain, but realizing you also need their allies to win the battle. 💪
yarn add express typescript @types/node
Now, let's create a src
folder where we'll keep our files, and an index.ts
file where our program will start. Like a true superhero, we need to have a strong starting point for our mission.
With TypeScript on our side, we were ready to take on the battle. But we soon realized that TypeScript was not just any ally - he was a joker, always cracking up jokes about our code. Luckily, he was also a controller, and he helped us keep our code under control.
Despite his humorous nature, we needed TypeScript in our battle, as he was the information broker. He could tell us what was wrong with our code before we even noticed it ourselves. But there was a catch: we had to communicate with him in his own language, Fe2O3. It was a magical language, and only the detective in the bat suit could understand it.
So we armed ourselves with TypeScript, the detective's bat suit, and a good sense of humor, and set out to conquer the world of Node.js with Express and TypeScript.
// tsconfig.json
{
"compilerOptions": {
// Set the ECMAScript version to ES2020
"target": "ES2020",
// Use a custom module system called NodeNext
"module": "NodeNext",
// Use the nodenext module resolution strategy
"moduleResolution": "nodenext",
// Enable compatibility with modules that use `export =` syntax
"esModuleInterop": true,
// Allow importing JSON files as modules
"resolveJsonModule": true,
// Generate source maps for the compiled code
"sourceMap": true,
// Specify the directory where the compiled code will be outputted
"outDir": "./dist",
// Enable strict type checking rules
"strict": true,
},
// Specify the files that should be included and excluded in the compilation process
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
And so we continued on our quest, and created the index.ts
file where we would start our magical process. This file would be the entry point to our application, and it would give multiple instructions to our magic.
First, we imported our friends Express and TypeScript, as well as some other helpful tools:
// we use default spell `express` which is the main spell
// and call named spell`Request` and `Response` which joker will need later
// to understand information, he's a psycho information broker after all
// ofc we will use ES module system
import express, { Request, Response } from "express";
// instantize an app from express() function
const app = express();
// setup a simple get route
// and return a test message
app.get("/", (req: Request, res: Response) => {
res.json({ test: "Ok" });
});
// and finally start the server at port 5000
const PORT = 5000;
app.listen(PORT, () => {
console.log("server has started on port");
console.log("http://localhost:" + PORT);
});
Excited to see our magical application come to life, we ran the node src/index.ts
command in our terminal, just like we had done before with our JavaScript projects. But instead of seeing our application start up, we were met with an error message:
import express, { Request, Response } from "express";
^^^^^^
SyntaxError: Cannot use import statement outside a module
Great! Now our friend Node understands the magic of ES modules, thanks to our configuration in package.json
.
{
"name": "expess_ts_setup",
"version": "1.0.0",
"main": "index.ts",
"license": "MIT",
// the new line we add
"type": "module", // "commonjs" is defualt, require() syntax
// ******************
"dependencies": {
"@types/node": "^18.16.3",
"express": "^4.18.2",
"typescript": "^5.0.4"
}
}
And let’s try again 🙂
node src/index.ts
node:internal/errors:464
ErrorCaptureStackTrace(err);
^
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for C:\expess_ts_setup\src\index.ts
Ofc it won’t work.
Our friend node engine
doesn’t understand typescript. We brought @types/node
so typescript
could understand node
Now it looks like we need another friend to explain typescript
to node
After some digging around we found out that there’s someone called ts-node
which can help us do that.
so we called him yarn add ts-node -D
Now instead of calling node
we call ts-node
yarn ts-node src/index.ts
However, it seems like we are still encountering an error:
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for C:\expess_ts_setup\src\index.ts
We added some more information to our tsconfig.json
file to help ts-node
understand how to transpile our TypeScript code into JavaScript that node
can understand. Here's the updated tsconfig.json
file:
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"moduleResolution": "nodenext",
"esModuleInterop": true,
"resolveJsonModule": true,
"sourceMap": true,
"outDir": "./dist",
"strict": true,
"baseUrl": "./",
"paths": {
"@controllers": ["src/controllers/index.js"],
"@router": ["src/router/index.js"],
"@endPoints": ["src/router/endPoints.enum.js"],
"@prisma": ["src/config/PrismaClient.js"]
}
},
// "include": ["src/**/*"],
// ts-node settings we added
"ts-node": {
"esm": true,
"compiler": "typescript"
}
// *****************
}
Oh yesss!! Finally we saw what we wanted to see
server has started on port
http://localhost:5000
Great! It's always satisfying to see things working as expected.
Now our magical tool works but we have to restart it every time we add some new features to it.
For that we all to whom to call 🙂
Our good old friend nodemon
, let's call him, yarn add nodemon -D
We can now call yarn nodemon src/index.ts
and our toll won’t have to restart for it to work with new features.
And lucky for us, since we already have ts-node
who understands typescript
, our nodemon
has learned to work with ts-node
automatically.
[nodemon] 2.0.22
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: ts,json
[nodemon] starting `ts-node src\index.ts` // nodemon is starting ts-node Wow!
server has started on port
http://localhost:5000
Phew!!
And we have finally make a magical tool that gives us power to build amazing web spell with ease. Don your developer cape and start building today!
Top comments (2)
It did not work for me. I'm not using yarn, so I don't know if that makes a difference.
You really are my true hero!