Using ExpressJS and Multer with TypeScript

Updated: February 6, 2024 By: Guest Contributor Post a comment

Introduction

When building a Node.js application with ExpressJS as the server framework and TypeScript as the language of choice, typing becomes an essential part of the development process. Using TypeScript, a superset of JavaScript, allows us to strongly type our variables, function return types, and even the request and response objects in our ExpressJS routes. This tutorial will focus on how to declare types when using Multer, a middleware for handling multipart/form-data, a common format for uploading files through forms.

Step-by-Step Instructions

Step #1 – Installation & Configuration

First, let’s set up our ExpressJS project with TypeScript and Multer installed.

npm init -y
npm install express @types/express multer @types/multer typescript ts-node
npx tsc --init

Ensure the generated tsconfig.json file has the following important settings enabled:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  }
}

Step #2 – Creating an Express App

Next, create an Express app in TypeScript. Here we’re focusing on the file uploading part with Multer.

import express from 'express';
import multer from 'multer';

const app = express();
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('file'), (req, res) => {
  // Assuming 'file' is the name of our file field in the form
  console.log(req.file);
  res.send('File uploaded successfully.');
});

app.listen(3000, () => console.log('Server started on port 3000'));

Step #3 – Typing req.file and req.boyd

So far, so good. However, when using TypeScript, we notice that req.file and req.body lack strong typing, which can result in potential errors slipping through during development. To tackle this issue, we declare types for both request body and files when using Multer with ExpressJS.

To begin, let’s extend the Express request type to include our file(s) and body types. This approach enhances readability and makes our codebase more robust.

import { Request } from 'express';
import { File } from 'multer';

declare module 'express-serve-static-core' {
  interface Request {
    body: MyRequestBodyType;
    file: File | null; // Single file upload
  }
}

interface MyRequestBodyType {
  // Define the types for your form fields here
  exampleField: string;
}

From this point, anywhere in our project where we make use of req.body or req.file, TypeScript will know the exact structure and types, reducing the chances of run-time errors due to incorrect data manipulation.

The beauty of TypeScript lies in its ability to catch errors at compile time rather than at runtime, and by incorporating strong typing for our request and response objects when dealing with files, we significantly lower the risk of runtime errors. Additionally, by leveraging the power of TypeScript with ExpressJS and Multer, developers can enjoy an improved development experience with more predictable code behavior.

Step #4 – Uploading Multiple Files with TypeScript (Optional)

As you advance, you might want to handle multiple files upload or even more complex structures. Multer’s flexibility paired with TypeScript’s strong typing can be exploited further to accommodate these scenarios. For instance:

app.post('/upload/multiple', upload.array('files', 5), (req, res) => {
  // Accesing multiple files
  console.log(req.files);
  res.send('Multiple files uploaded successfully.');
});

In this case, we need to modify our type declarations for handling multiple files:

declare module 'express-serve-static-core' {
  interface Request {
    files: File[] | null; // Multiple file upload
  }
}

Final Words

This tutorial has introduced the basics of declaring types in your ExpressJS and Multer project using TypeScript. Adopting this practice not only enhances the reliability of your code but also improves the development experience by leveraging strong typing throughout your application. As TypeScript continues to gain popularity in the JavaScript community, mastering these techniques will undoubtedly be a valuable asset for any developer.