Saul Espinoza
Saul Espinoza

Reputation: 139

TypeScript and NestJs: Spread types may only be created from object types

I am trying to pass two parameters with spread operator from the book.controller, to the book.service.ts service, however I am getting the following error

Spread types may only be created from object types

It should be noted that passing a single parameter with spread operator if it works

I attached the controller and the service:

book.controller.ts

    @Controller('book')
    export class BookController {
        constructor(
            private readonly _bookService: BookService
        ) { }
    
//it works
        @Post()
        @Roles(RoleType.ADMIN, RoleType.MANAGER)
        @UseGuards(AuthGuard(), RoleGuard)
        @UseInterceptors(FileInterceptor('image'))
        createBook(@UploadedFile() file: any, @Body() role: Partial<CreateRoleDto>) {
            return this._bookService.create({
                ...role,
                image: file?.filename
            });
        }
    
    //In this request is where I have the aforementioned error
    
        @Post('author')
        @Roles(RoleType.GUEST)
        @UseGuards(AuthGuard(), RoleGuard)
        @UseInterceptors(FileInterceptor('image'))
        createBookByAuthor(@UploadedFile() file: any, @Body() role: Partial<CreateBookDto>, @GetUser('id') authorId: number) {
            return this._bookService.createByAuthor({
                ...role,
                ...authorId,
                image: file?.filename
            })
        }
    }

book.service.ts

@Injectable()
export class BookService {
    constructor(
        @InjectRepository(BookRepository)
        private readonly _bookRepository: BookRepository,

        @InjectRepository(UserRepository)
        private readonly _userRepository: UserRepository
    ) { }

    async create(book: Partial<CreateBookDto>): Promise<ReadBookDto> {
        const authors: User[] = [];
        for (const authorId of book.authors) {
            const authorExists = await this._userRepository.findOne(authorId, {
                where: { status: status.ACTIVE }
            });
            if (!authorExists) {
                throw new NotFoundException(
                    `There's  not an author with  this id: ${authorId}`
                );
            };
            const isAuthor = authorExists.roles.some(
                (role: Role) => role.name === RoleType.GUEST
            );
            if (!isAuthor) {
                throw new UnauthorizedException(
                    `This user ${authorId} is not an author`
                )
            }
            authors.push(authorExists);
        }
        const savedBook: Book = await this._bookRepository.save({
            name: book.name,
            description: book.description,
            image: book.image,
            authors
        })
        return plainToClass(ReadBookDto, savedBook);
    }

    async createByAuthor(book: Partial<CreateBookDto>, authorId: number): Promise<ReadBookDto> {
        const author = await this._userRepository.findOne(authorId, {
            where: { status: status.ACTIVE }
        });
        const isAuthor = author.roles.some(
            (role: Role) => role.name === RoleType.GUEST
        );
        if (!isAuthor) {
            throw new UnauthorizedException(`This user ${authorId} is not an author`)
        }
        const savedBook: Book = await this._bookRepository.save({
            name: book.name,
            description: book.description,
            image: book.image,
            authors: [author]
        });
        return plainToClass(ReadBookDto, savedBook);
    }
}

Help!! Thanks

Upvotes: 0

Views: 704

Answers (1)

Hadas
Hadas

Reputation: 64

spread operator can be used on objects or arrays for example https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

you can't iterate over a number so it also can't be spreaded. also seems that the authorId is a different parameter (not inside the book)

in your case you can just call it like this:

this._bookService.createByAuthor({
                ...role,
                image: file?.filename
            }, authorId)

Upvotes: 2

Related Questions