使用multer和express与typescript

12

背景

我正在制作一个简单的网站,用户可以上传图像。 我使用的是Node/React/Multer/Typescript技术。

问题

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

TypeScript的智能感知会显示以下形式的错误。

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

但是,我不明白为什么会出现这个错误。我认为files对象的类型应该是{ [fieldname: string]: File[]; },意味着files对象可以有一个字符串属性。
所以我用一个简单的例子进行测试。
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

我不知道为什么files对象不能有companyImage属性。
请检查一下。
4个回答

22

我不知道你是否成功解决了你的问题,但我也遇到了相同的问题,并且必须明确地告诉 TypeScript 我的 req.files 属性的类型,就像这样:

我不确定您是否已经成功解决了您的问题,但是我也遇到了相同的问题,必须明确告诉TypeScript我的req.files属性的类型,如下所示:

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

请注意,由于我正在使用upload.fields(...),因此我没有指定req.files也可以是一个简单的Express.Multer.File[]


2
Express没有导出名为Multer的成员。 - GN.
7
请执行 npm install --save-dev @types/multer 命令以安装 multer 类型声明。 - Mickael V.
这样做可以解决问题的原因是因为req.files的类型被定义为具有字段名称或数组的对象。数组中不包含“companyImage”属性。一个更正确的解决方案(不需要显式类型转换)是先检查req.files是否为一个数组。const files = req.files; if(Array.isArray(files)) { throw new Error(); } else { console.log(files.companyImage) } - Brian Hannay

2

由于你正在使用TypeScript,请创建一个文件接口,如下所示:

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

然后声明 const files = req.files as IFile[],并记得在 types/express/index.d.ts 中添加 files: IFile;

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

0
在这里,我在我的TypeScript版本(^5.2.2)上遇到了同样的问题。尽管我找不到Multer上的任何类型,但我在这里解决了我的问题。
在全局类型文件中声明命名空间。
export type IFile = {
  fieldname: string;
  originalname: string;
  encoding: string;
  mimetype: string;
  buffer: Buffer;
  size: number;
};

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

然后在需要的地方使用它们,并声明类型。
const fileInfo = (req.files as { fileName?: IFile[] })['fileName']?.[0];

在这里,fileName 包含了你的 formData 文件名。

-1
我通过Object.assign(req.files)解决了这个问题,然后你可以将它作为一个对象来处理:console.log(s.image[0].path);

这个问题明确提到了使用TypeScript。去掉类型的答案违背了使用TypeScript的初衷。你可以在不去掉类型的情况下处理req.files,正如此问题的另一个答案中所提到的。 - Brian Hannay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接