Factory function for file validators

A more encapsulated way to instantiate file validators.

Let's then create this structure in src -> files. There, first we'll create the file util -> file-validation.util, where we'll define a type for the allowed file types.

type FileType = 'png' | 'jpeg' | 'pdf';

Here, we use jpeg instead of jpg because the comparison is made with the Media Type, which is the extension's complete name. Due to this, the short form would not work.

Now, let's create a factory function, which will return the two validators, so that we don't need to manually instantiate them. The function will have as parameters the maxSize and the fileTypes, and then returns the two validators. Therefore, this will be its signature:

export const createFileValidators = (
  maxSize: number,
  ...fileTypes: NonEmptyArray<FileType>
): FileValidator[] => {};

Let's then create the fileTypeRegex from the received fileTypes.

const fileTypeRegex = new RegExp(fileTypes.join('|'));

Then, return the two validators.

return [
  new MaxFileSizeValidator({ maxSize }),
  new FileTypeValidator({ fileType: fileTypeRegex }),
];

There is still a problem: the maxSize in bytes. To fix this, we can use the bytes library, which is already installed. We just need to install its typing.

yarn add -D @types/bytes

Import it like the following: import * as bytes from 'bytes';

What's left to do is to change the type of the maxSize parameter to string, and then use the bytes library to transform this string to a value in bytes when instantiating the first validator.

new MaxFileSizeValidator({ maxSize: bytes(maxSize) }),

And, a last improvement we could make, is to create the type FileSize. With it, we can enforce that the maxSize should be a string containing a number followed by either KB, MB or GB.

type FileSize = `${number}${'KB' | 'MB' | 'GB'}`;

Back in the route, our validators can now be created like this:

validators: createFileValidators('2MB', 'png', 'jpeg')

Commit - Using a factory function to create file validators

Last updated