Reputation: 31
express-fileupload has declaration like this:
declare namespace fileUpload {
class FileArray {
[index: string]: UploadedFile | UploadedFile[]
}
interface UploadedFile {
name: string;
encoding: string;
mimetype: string;
data: Buffer;
truncated: boolean;
mv(path: string, callback: (err: any) => void): void;
mv(path: string): Promise<void>;
}
Then in controller Iam using it as:
const file: UploadedFile | UploadedFile[] = req.files.file;
But now TypeScript monits
Property 'name' does not exist on type 'UploadedFile | UploadedFile[]'.
Property 'name' does not exist on type 'UploadedFile[]'.
for file.name
Bacause In Array Type theres no poperty "name".
How tyo handle this situtuation ? A try
if (file instanceof Array)
if (file typeof UploadedFile[])
But this not works.
Upvotes: 0
Views: 1238
Reputation: 7916
The if (file typeof UploadedFile[])
part will not work because typeof
is a JS runtime check, and UploadedFile[]
is a type. The concept of types does not really exist at runtime, therefore it's impossible to execute the statement.
But the first check for file
being an array should actually be enough. By writing code that handles the type UploadedFile | UploadedFile[]
you're basically trusting any variable that is assigned that type to have a value of that type at runtime. So if it's not an array, it must be a value of type UploadedFile
:
if (Array.isArray(req.files.file)) {
// It must be an array of UploadedFile objects...
} else {
// It must be a single UploadedFile object...
}
The tedious part is that as long as a variable has a union type like this, you'd have to write constructs similar to if...else anywhere you want to perform operations on the variable (read it, transform it, or otherwise use it). Is there a cleaner way?
You could normalize the value of file
to always be an array, and then always treat it as such
If req.files.file
is an array, let myFiles
be req.files.file
. Otherwise let myFiles
be an array containing 1 element which is req.files.file
:
const myFiles: UploadedFile[] = Array.isArray(req.files.file)
? req.files.file
: [req.files.file];
Now consider having a function handleSingleFile
that you must run for all files that came out of req.files.file
. Instead of writing:
if (Array.isArray(req.files.file)) {
req.files.file.forEach((file) => handleSingleFile(file));
} else {
handleSingleFile(req.files.file);
}
...you know that myFiles
will always be an array:
myFiles.forEach((file) => handleSingleFile(file));
Upvotes: 2