> For the complete documentation index, see [llms.txt](https://kinesis-school-of-programming.gitbook.io/nestjs-unleashed/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kinesis-school-of-programming.gitbook.io/nestjs-unleashed/extra-module-4-file-management/file-validation/factory-function-for-file-validators.md).

# Factory function for file validators

A more encapsulated way to instantiate file validators.

Let's then continue this structure in <mark style="color:purple;">src</mark>/<mark style="color:purple;">files</mark>. There, first we'll create the file <mark style="color:purple;">util</mark>/<mark style="color:purple;">file-validation.util</mark>, where we'll define a **type** for the allowed file types.

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

{% hint style="info" %}
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 <mark style="color:red;">not</mark> work.
{% endhint %}

Now, let's create a factory function that returns the two validators, so that we don't need to manually instantiate them. The function will have, as parameters, the <mark style="color:blue;">`maxSize`</mark> and the <mark style="color:blue;">`fileTypes`</mark>, and then returns the two validators. Therefore, this will be its signature:

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

Let's then create the <mark style="color:blue;">`fileTypeRegex`</mark> from the received <mark style="color:blue;">`fileTypes`</mark>.

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

Then, return the two validators.

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

There is still a problem: the <mark style="color:blue;">`maxSize`</mark> in bytes. To fix this, we can use the [bytes](https://www.npmjs.com/package/bytes) library, which is already installed. We just need to install its typing.

```sh
yarn add -D @types/bytes
```

{% hint style="info" %}
Import it while adding <mark style="color:blue;">`* as`</mark>.
{% endhint %}

What's left to do is to change the type of the <mark style="color:blue;">`maxSize`</mark> parameter to <mark style="color:blue;">string</mark>, and then use the **bytes** library to transform this string to a value in bytes when instantiating the first validator.

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

And, a last improvement we could make, is to create the **template literal type** <mark style="color:blue;">`FileSize`</mark>. With it, we can enforce that the <mark style="color:blue;">`maxSize`</mark> should be a string containing a <mark style="color:blue;">number</mark> followed by either <mark style="color:blue;">KB</mark>, <mark style="color:blue;">MB</mark> or <mark style="color:blue;">GB</mark>. We can also create a type to represent these magnitudes.

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

Back in the route, our <mark style="color:blue;">`validators`</mark> can now be created like this:

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

<mark style="color:green;">**Commit**</mark> - Using factory function to create file validators
