Using TypeScript and NestJs: Spread types can only be generated from object types

I'm encountering an issue while trying to pass two parameters using the spread operator from the book.controller to the book.service.ts service. The error message I'm receiving is:

Spread types may only be created from object types

It's worth mentioning that passing a single parameter with the spread operator works fine.

Below are snippets of the controller and service files:

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
            });
        }
    
    //The error occurs in this request
    
        @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);
    }
}

Any help would be greatly appreciated! Thank you!

Answer №1

The spread operator is a useful tool in JavaScript that allows you to easily manipulate objects or arrays. You can learn more about it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

It's important to note that you cannot iterate over a number, so you cannot use the spread operator on numbers either. Additionally, the authorId seems to be a separate parameter and not nested within the book.

In your specific scenario, you can simply implement it like this:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Avoiding caching of GET requests in Angular 2 for Internet Explorer 11

My rest endpoint successfully returns a list when calling GET, and I can also use POST to add new items or DELETE to remove them. This functionality is working perfectly in Firefox and Chrome, with the additional note that POST and DELETE also work in IE ...

Facing issues with module resolution while attempting to debug in VSCode

I'm currently in the process of debugging a module within our project. However, I've encountered difficulties attaching the debugger on Visual Studio Code since we recently changed the directory structure. Here is my tsconfig: { "compilerOptio ...

The method of having two consecutive subscribe calls in Angular2 Http

Can the Subscribe method be called twice? I am attempting to create an API factory that stores data in the factory and allows different components to use that data for each AJAX call. The factory: export class api { result = []; constructor (p ...

What seems to be the issue with the useState hook in my React application - is it not functioning as

Currently, I am engrossed in a project where I am crafting a Select component using a newfound design pattern. The execution looks flawless, but there seems to be an issue as the useState function doesn't seem to be functioning properly. As a newcomer ...

Error: Attempting to access 'pageContext' property on undefined object, resulting in TypeError while utilizing sp pnp v3

I am currently following a tutorial to build a webpart using SPFX and SP/PNP v3: https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/use-sp-pnp-js-with-spfx-web-parts I have also consulted: Here is the main .ts file: public async onIn ...

There are no matching overloads in React for this call

Below is an error message in the code. It seems to be related to the usage of <IHistorical[]> in useQuery, but unfortunately, I haven't found a solution for it yet. Overload 1 of 2, '(props: Props | Readonly<Props>): ReactApexChart& ...

Retrieve the essential information needed from the REST API

I have a test wordpress blog set up. To enhance the functionality, I developed an angular app that utilizes the wordpress rest api. The app makes a call to an endpoint to retrieve categories. However, the JSON response contains unnecessary data for my appl ...

The deployment on Vercel for a Node Express and TypeScript project is experiencing issues with building

After uploading my project with node using express + typescript, I encountered a problem. The app generates a folder called dist for building, but when vercel deployed my app, it didn't run the build command. To resolve this issue, I had to manually b ...

What sets apart the utilization of add versus finalize in rxjs?

It appears that both of these code snippets achieve the same outcome: Add this.test$.pipe(take(1)).subscribe().add(() => console.log('added')); Finalize this.test$.pipe(take(1), finalize(() => console.log('finalized'))).sub ...

Unable to store the outcomes from [ngbTypeahead] in [resultTemplate]

I'm trying to integrate ngbTypeahead into my HTML using the code snippet below <ng-template #rt let-r="result" let-t="term"> <ngb-highlight [result]="r.FirstName" [term]="t"></ngb-highlight> </ng-template> <input name ...

Strategies for resolving a mix of different data types within a single parameter

Here, I am setting up the options params to accept a value that can either be a single string or another object like options?: string[] | IServiceDetail[] | IServiceAccordion[]; However, when attempting to map these objects, an error is encountered: Prope ...

Extending injections in Angular 5 by inheriting from a base class

I have created a class with the following structure: @Injectable FooService { constructor(protected _bar:BarService){ } } Then, I extended this class as shown below: @Injectable ExtFooService extends FooService { constructor(_bar:BarServi ...

TS1261: The file name 'xxx' that is already included is different from the file name 'xxx' only in terms of casing

In my project, there is a file located at /app/client/modules/activity/pages/New/hooks.ts. The folder name is New, with the first letter capitalized. During the webpack build process, I encountered the following error: ERROR in /root/app/client/modules/ac ...

Troubleshooting issues with TypeScript D3 v4 module import functionality

As I embark on the journey of creating a miniature JS library using D3 to visualize line charts, I find myself navigating unfamiliar waters. However, I believe that deep diving into this project is the most effective way for me to learn. Below is the cont ...

Having trouble locating an Ionic module with your Ionic Web Builder?

Currently, I am working on building my Ionic app using their web build system. In my app.component.ts file, I have included the following import statement: import { File } from '@ionic-native/File/ngx'; Although this project compiles successful ...

Guide on specifying the return type of a generic class when using TypeScript

The code I am working with is structured like this: import * as events from 'events' // Utilizing Node.js events module // My custom implementation of EventEmitter with enhanced typing interface IEventEmitter<EventTypes> { /* ... */ } // ...

Adjusting characteristics in Angular dynamically through JSON

Having trouble changing the value of [icon]="reactAtom" to use a JSON value? Need assistance in updating the [icon] value based on the 'featureItem' received from the parent component. HTML <div> <fa-icon [icon]="reactAtom" class="i ...

Is there a way to modify the antd TimePicker to display hours from 00 to 99 instead of the usual 00 to 23 range?

import React, { useState } from "react"; import "./index.css"; import { TimePicker } from "antd"; import type { Dayjs } from "dayjs"; const format = "HH:mm"; const Clock: React.FC = () =& ...

Deleting a file from the assets folder in Angular for good

I am attempting to permanently delete a JSON file from the assets folder using my component. Despite trying to use HttpClient, I encounter no errors but the file remains undeleted. constructor(http: HttpClient){} remove() { this.http.delete('assets ...

Choosing radio buttons within rows that contain two radio buttons using ngFor

This section showcases HTML code to demonstrate how I am iterating over an array of objects. <div class="row" *ngFor="let item of modules; let i = index;"> <div class="col-md-1 align-center">{{i+1}}</div> <div class="col-md- ...