10 Mar 2025
•
Ernesto Ballon
•
5 min read
Migrating your Node.js/Express application from JavaScript to TypeScript enhances maintainability, scalability, and type safety. This guide provides a structured approach to smoothly transition your project.
Before diving into the migration, ensure you complete these essential setup steps:
✅ Install TypeScript and type definitions
✅ Create a tsconfig.json
file
✅ Update package.json
scripts
✅ Define custom type definitions
Rename your JavaScript files to TypeScript files by changing the extensions from .js
to .ts
:
src/server.js → src/server.ts
scripts/deploy.js → scripts/deploy.ts
For files that include JSX, use the .tsx
extension.
TypeScript requires explicit file extensions when using ES module imports:
// Before
import User from '../models/User';
// After
import User from '../models/User.js';
Although your TypeScript files end in .ts
, compiled JavaScript files will have .js
, so ensure imports reflect this.
Explicitly defining types improves code reliability:
// Before
function getUserById(id) {
// ...
}
// After
function getUserById(id: string): Promise<User | null> {
// ...
}
Secure your environment variables using TypeScript:
// src/config/env.ts
import dotenv from 'dotenv';
import { EnvVariables } from '../types/index.js';
dotenv.config();
export const env: EnvVariables = {
MONGO_URI: process.env.MONGO_URI || 'mongodb://localhost:27017/your_database',
PORT: process.env.PORT || '3000',
CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
// Add other environment variables
};
For custom middleware, define explicit types:
// src/middleware/auth.ts
import { Request, Response, NextFunction } from 'express';
import { AuthenticatedRequest } from '../types/index.js';
export const authMiddleware = (
req: Request,
res: Response,
next: NextFunction
) => {
const authenticatedReq = req as AuthenticatedRequest;
// ... authentication logic
next();
};
Enhance your Mongoose models with TypeScript for better data consistency.
// Example in src/models/exampleModel.ts
Modify your package.json
scripts to support TypeScript:
{
"scripts": {
"build": "tsc",
"start": "node dist/server.js",
"dev": "nodemon --exec ts-node src/server.ts"
}
}
Use these commands:
npm run build
– Compile TypeScript to JavaScriptnpm start
– Run the production servernpm run dev
– Watch mode with nodemon
and ts-node
Install missing type definitions:
npm install --save-dev @types/[library-name]
Sometimes TypeScript cannot infer the correct type:
const userData = JSON.parse(jsonString) as User;
any
as a Temporary SolutionWhen unsure about a type, use any
but replace it later with precise typing:
let complexData: any = fetchComplexData();
Create a type declaration file for unsupported libraries:
// src/types/declarations.d.ts
declare module 'module-without-types' {
export function someFunction(param: string): void;
export const someValue: number;
}
✅ Continue migrating files incrementally
✅ Integrate TypeScript-based testing
✅ Configure ESLint for TypeScript
✅ Define interfaces for API responses
By following these steps, your Node.js/Express application will be fully migrated to TypeScript, ensuring a more structured, scalable, and maintainable codebase. 🚀