Sling Academy
Home/Node.js/Using ExpressJS and Multer with TypeScript

Using ExpressJS and Multer with TypeScript

Last updated: February 06, 2024

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.

Next Article: ExpressJS: How to pass variables to Pug templates

Previous Article: ExpressJS: Using MORGAN to Log HTTP Requests

Series: Node.js & Express Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates
  • ExpressJS: How to pass variables to Pug templates