Byeongin Yoon
Byeongin Yoon

Reputation: 4037

Using multer and express with typescript

Background

I'm making a simple website in which a user can upload an image. I'm using Node/React/Multer/Typescript.

Problem

app.post('/admin/uploads', async (req, res) => {
  uploadHandler(req, res, (err) => {
    ...
    if ( req.files.companyImage !== undefined ) {
      ...
    }
    res.sendStatus(201);
  });
});

typescript intellisense shows error like below.

Property 'companyImage' does not exist on type '{ [fieldname: string]: File[]; } | File[]'.
Property 'companyImage' does not exist on type '{ [fieldname: string]: File[]; }'.ts(2339)

But, I cannot understand why this is error. I think files object has type { [fieldname: string]: File[]; }. This means files object can have property which is string.

So I test with simple example.

type myType = {
  [fieldName: string]: number
}

let req: myType = {
  a: 333,
  b: 344
}

console.log(req.a);
console.log(req.c); // undefined but intellisense don't show error

I don't know why files object cannot have companyImage property.

Check please.

Upvotes: 12

Views: 20944

Answers (4)

Kayes
Kayes

Reputation: 427

Here, I have the same issue on my TypeScript version (^5.2.2). Even though I can't find any type on Multer, here I do solve my issue.

Declare namespace on global type file

export type IFile = {
  fieldname: string;
  originalname: string;
  encoding: string;
  mimetype: string;
  buffer: Buffer;
  size: number;
};

declare global {
  namespace Express {
    type Request = {
      files: IFile;
    };
  }
}

Then use them where I need with the declared type

const fileInfo = (req.files as { fileName?: IFile[] })['fileName']?.[0];

Here, fileName contains your formData file name

Upvotes: 0

Francois MUGOROZI
Francois MUGOROZI

Reputation: 299

Since you are using typescript, create an interface for file as

interface IFile {
  fieldname: string;
  originalname: string;
  encoding: string;
  mimetype: string;
  buffer: Buffer;
  size: number;
}

and then declare const files = req.files as IFile[] and remember to add files: IFile; in the types/express/index.d.ts as

declare global {
  namespace Express {
    interface Request {
      files: IFile;
    }
  }
}

Upvotes: 3

commedy nghit
commedy nghit

Reputation: 9

I solved it by Object.assign(req.files) then you can deal with it as an object: console.log(s.image[0].path);

Upvotes: -1

Michael Tremblay
Michael Tremblay

Reputation: 386

I don't know if you successfully resolved your issue, but I had the same and had to explicitly tell TypeScript the type of my req.files property like this:

const files = req.files as { [fieldname: string]: Express.Multer.File[] };

Note that, since I'm using upload.fields(...), I'm not specifying that req.files can also be a simple Express.Multer.File[].

Upvotes: 26

Related Questions