我正在从 JS 迁移到 TS,并在此过程中遇到了一些问题。我使用广为人知的 multer 包和自定义存储引擎 multer-s3 来高效地将传入文件直接流式传输到 AWS。
自定义存储引擎 multer-s3 提供了自己的“文件”属性定义,扩展了 multer 的定义。 multer-s3 的
index.d.ts
文件如下所示(multer-s3 的完整类型定义可以在 here 找到):
declare global {
namespace Express {
namespace MulterS3 {
interface File extends Multer.File {
bucket: string;
key: string;
acl: string;
contentType: string;
contentDisposition: null;
storageClass: string;
serverSideEncryption: null;
metadata: any;
location: string;
etag: string;
}
}
}
}
每当我解析传入文件时,multer 都会使用自己的 File 定义,而不是 multer-s3 的定义,这会导致
location
等属性在 req.file
对象上不可用。
我现在的问题:如何让 multer 使用 multer-s3 的文件定义而不是它自己的文件定义?在迁移到 Typescript 之前,multer-s3 的“文件”类型定义中包含的所有属性都可以在
req.file
下访问 - 不幸的是,Typescript 无法识别这一点。到目前为止,我正在使用一种解决方法,在类型为 Express.MulterS3.File
: 的请求接口上创建一个新属性
export default interface IRequest extends express.Request {
processedFile?: Express.MulterS3.File;
}
然后,在解析中间件内部,将
req.file
属性向下转换为 Express.MulterS3.File
,这使得所需的属性可用:
export const acceptProfilePicUpload = async function (
req: IRequest,
res: express.Response,
next: express.NextFunction
) {
try {
await new Promise((resolve, reject) => {
multerUpload(req, res, (err: any) => {
if (err) reject(err);
else resolve(true);
});
});
if (!req.file)
throw new Error("file missing");
req.processedFile = req.file as Express.MulterS3.File; // this is how I get TS to user multer-s3's type definitions - is there a better solution?
next();
} catch (error) {
console.log(error);
next(error);
}
};
但是,我不确定这是否是正确的方法,并恳请您就这个问题提供帮助。我的目标是简单地让
req.file
成为 Express.MulterS3.File
类型,而不是 Express.Multer.File
。
也许你们中的一些人知道问题出在哪里,或者在打字稿中使用 multer-s3 和 multer 时自己遇到过。 任何帮助将不胜感激!
我修复了合并类型
Express.Multer.File
和 Express.MulterS3.File
的问题。
首先,您必须覆盖
Express.Request.file
中的 express
类型。您可以使用 typeRoots
中的 tsconfig.json
键来完成此操作。键接收一个字符串数组,每个字符串必须是一个指定文件夹的路径,其作用类似于 ./node_modules/@types
。使用此键,您将能够覆盖 express
或任何其他库中的类型。
这是我的
typeRoots
:
"typeRoots": [
"./node_modules/@types",
"./src/@types"
],
然后,使用您的
Express.Request.file
声明创建一个文件,例如,这是我的 express.d.ts
(该文件可以有任何名称):
declare namespace Express {
export interface Request {
file: Express.Multer.File & Express.MulterS3.File;
}
}
如果你想只改变
req.file
的类型而不是两者,你可以写:Express.MulterS3.File
declare namespace Express {
export interface Request {
file: Express.MulterS3.File;
}
}
的类型专门更改为
req.file
,您可以将以下代码添加到您的 Express.MulterS3.File
文件中:express.d.ts
这将有效地使用
declare global {
namespace Express {
namespace Multer {
interface File {
bucket: string;
key: string;
acl: string;
contentType: string;
contentDisposition: null;
storageClass: string;
serverSideEncryption: null;
metadata: any;
location: string;
etag: string;
}
}
}
}
的属性覆盖
Express.Multer.File
类型,允许您在处理上传的文件时在 TypeScript 代码中使用 S3 特定的属性。