TS2416 & TS2322 errors related to the built-in FileValidator implementations
scur-iolus opened this issue ยท 8 comments
Did you read the migration guide?
- I have read the whole migration guide
Is there an existing issue that is already proposing this?
- I have searched the existing issues
Potential Commit/PR that introduced the regression
No response
NestJS version
9.4.3 -> 10.0.0
Describe the regression
TS errors after upgrading to v10.0.0
. I'm not sure if this is a regression or if the documentation hasn't been updated yet. In any case, there seems to be a breaking change which isn't clearly reported. The issue stems from a short block of code very similar to the one given in the documentation (see below). When trying to build my application (yarn run build
), I get these errors:
node_modules/@nestjs/common/pipes/file/file-type.validator.d.ts:19:5 - error TS2416: Property 'isValid' in type 'FileTypeValidator' is not assignable to the same property in base type 'FileValidator<FileTypeValidatorOptions>'.
Type '<TFile extends IFile = any>(file: TFile) => boolean' is not assignable to type '<TFile extends IFile = any>(file?: TFile | undefined) => boolean | Promise<boolean>'.
Types of parameters 'file' and 'file' are incompatible.
Type 'TFile | undefined' is not assignable to type 'IFile'.
Type 'undefined' is not assignable to type 'IFile'.
19 isValid<TFile extends IFile = any>(file: TFile): boolean;
~~~~~~~
node_modules/@nestjs/common/pipes/file/max-file-size.validator.d.ts:16:5 - error TS2416: Property 'isValid' in type 'MaxFileSizeValidator' is not assignable to the same property in base type 'FileValidator<MaxFileSizeValidatorOptions>'.
Type '<TFile extends IFile = any>(file: TFile) => boolean' is not assignable to type '<TFile extends IFile = any>(file?: TFile | undefined) => boolean | Promise<boolean>'.
Types of parameters 'file' and 'file' are incompatible.
Type 'TFile | undefined' is not assignable to type 'IFile'.
Type 'undefined' is not assignable to type 'IFile'.
16 isValid<TFile extends IFile = any>(file: TFile): boolean;
~~~~~~~
src/MY_PATH.controller.ts:44:11 - error TS2322: Type 'MaxFileSizeValidator' is not assignable to type 'FileValidator<Record<string, any>>'.
Types of property 'isValid' are incompatible.
Type '<TFile extends IFile = any>(file: TFile) => boolean' is not assignable to type '<TFile extends IFile = any>(file?: TFile | undefined) => boolean | Promise<boolean>'.
44 new MaxFileSizeValidator({ maxSize: MAX_FILE_SIZE }),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/MY_PATH.controller.ts:45:11 - error TS2322: Type 'FileTypeValidator' is not assignable to type 'FileValidator<Record<string, any>>'.
Types of property 'isValid' are incompatible.
Type '<TFile extends IFile = any>(file: TFile) => boolean' is not assignable to type '<TFile extends IFile = any>(file?: TFile | undefined) => boolean | Promise<boolean>'.
45 new FileTypeValidator({ fileType: VALID_FILE_TYPES }),
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Everything works smoothly with the previous version of NestJS (yarn upgrade @nestjs/common@^9.4
). I've checked the migration guide and haven't noticed any reference to the FileValidator
.
Minimum reproduction code
Input code
@UploadedFile(
new ParseFilePipe({
validators: [
new MaxFileSizeValidator({ maxSize: 1000 }),
new FileTypeValidator({ fileType: 'image/jpeg' }),
],
}),
)
file: Express.Multer.File,
This piece of code is directly extracted from the documentation.
Expected behavior
No TS error :)
Other
No response
Please provide a minimum reproduction repository. You can start from this minimal project.
why reproductions are required
Here it is.
Side note, you need to turn on these settings in your tsconfig
file:
"strict": true,
"skipLibCheck": false,
Published as v10.0.1
is this issue fixed cause I m currently on version 10.0.1 and the issue persists.
@sumann7916 this issue is not present in the latest version (10.0.5)
The issue still remains for me. This is the error I get now, with v10.0.5:
Property 'isValid' in type 'FileExtensionValidator' is not assignable to the same property in base type 'FileValidator<{ allowedExtensions: string[]; }>'.
Type '(file?: File) => boolean | Promise<boolean>' is not assignable to type '<TFile extends IFile = any>(file?: TFile) => boolean | Promise<boolean>'.
Types of parameters 'file' and 'file' are incompatible.
Type 'TFile' is not assignable to type 'File'.
Type 'IFile' is missing the following properties from type 'File': fieldname, originalname, encoding, stream, and 4 more.
isValid(file?: Express.Multer.File): boolean | Promise<boolean> {
for this class:
export class FileExtensionValidator extends FileValidator<{
allowedExtensions: string[]
}> {
isValid(file?: Express.Multer.File): boolean | Promise<boolean> {
return this.validationOptions.allowedExtensions.includes(extname(file.originalname))
}
}
And I don't understand this error. Express.Multer.File
implements the IFile
interface, and <TFile extends IFile = any>
means that TFile (which is Express.Multer.File in my case) has to implement IFile, right? But from the error message, it seams that IFile is supposed to implement TFile? Apologies if I don't understand fully how generic classes work in Typescript
Probably due to the fact typescript does not know that. I think creating a new type which implements IFile will probably work.