You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express中使用Multer遇到的两个TypeScript错误求助

Express + Multer + Sharp 图片上传的TypeScript错误修复

原始代码

import multer, { FileFilterCallback } from "multer";
import sharp from "sharp";
import { NextFunction, Request, Response } from "express";

const multerStorage = multer.memoryStorage();

const multerFilter = (
  req: Request,
  file: Express.Multer.File,
  cb: FileFilterCallback
) => {
  if (file.mimetype.startsWith("image")) {
    cb(null, true);
  } else {
    cb(new Error("Not an image! Please upload only images."), false);
  }
};

const upload = multer({ storage: multerStorage, fileFilter: multerFilter });

export const uploadRecipeImages = upload.array("images", 6);

export const resizeRecipeImages = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  if (!req.files?.images) return next();

  req.body.images = [];

  await Promise.all(
    req.files.images.map(async (file, index) => {
      const filename = `recipe-${req.params.id}-${Date.now()}-${
        index + 1
      }.jpeg`;

      await sharp(file.buffer)
        .resize(1024, 1024)
        .toFormat("jpeg")
        .jpeg({ quality: 90 })
        .toFile(`public/img/recipes/${filename}`);

      req.body.images.push(filename);
    })
  );

  next();
};

错误1:cb(new Error(...), false)类型不兼容

报错信息:Argument of type 'Error' is not assignable to parameter of type 'null'.ts(2345)

修复方案

问题源于FileFilterCallback的类型推断限制,直接显式定义回调参数类型即可解决:

const multerFilter = (
  req: Request,
  file: Express.Multer.File,
  // 显式指定回调参数类型,替代FileFilterCallback
  cb: (error: Error | null, acceptFile: boolean) => void
) => {
  if (file.mimetype.startsWith("image")) {
    cb(null, true);
  } else {
    cb(new Error("Not an image! Please upload only images."), false);
  }
};

错误2:req.files?.images属性不存在

报错信息:Property 'images' does not exist on type '{ [fieldname: string]: File[]; } | File[]'. Property 'images' does not exist on type 'File[]'.ts(2339)

修复方案(二选一)

方案1:适配upload.array的返回格式

upload.array("images", 6)会将上传文件存入req.files数组(类型为File[]),而非req.files.images对象。修改判断逻辑:

export const resizeRecipeImages = async (
  req: Request,
  res: Response,
  next: NextFunction
) => {
  // 直接判断req.files是否存在且不为空数组
  if (!req.files || req.files.length === 0) return next();

  req.body.images = [];

  await Promise.all(
    // 遍历req.files数组,而非req.files.images
    req.files.map(async (file, index) => {
      const filename = `recipe-${req.params.id}-${Date.now()}-${index + 1}.jpeg`;

      await sharp(file.buffer)
        .resize(1024, 1024)
        .toFormat("jpeg")
        .jpeg({ quality: 90 })
        .toFile(`public/img/recipes/${filename}`);

      req.body.images.push(filename);
    })
  );

  next();
};

方案2:改用upload.fields实现req.files.images格式

如果想保留req.files.images的写法,将upload.array替换为upload.fields,并扩展Express Request类型:

  1. 修改上传中间件:
// 替换原来的uploadRecipeImages
export const uploadRecipeImages = upload.fields([
  { name: "images", maxCount: 6 }
]);
  1. 在项目根目录创建types/express.d.ts文件,扩展Request类型:
declare global {
  namespace Express {
    interface Request {
      files?: {
        images?: Express.Multer.File[];
      };
    }
  }
}

这样req.files?.images的类型就能被TypeScript正确识别。


内容的提问来源于stack exchange,提问作者Mohammad Reza Ghasemi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:47:13