Search code examples
typescriptpostgresqlnestjsprisma

Can not create an item with Prisma, Postgresql and Nestjs


I am building a clothes marketplace but i get an error when I try to create a clothes Item. Here is an error in createItem Service

Types of property 'userId' are incompatible.
Type 'number' is not assignable to type 'never'.

Here is my models in Prisma

model User {
  id       Int       @id @default(autoincrement())
  email    String    @unique
  fullName String
  password String
  items    Item[]
  location Location?
  phone    String?
  image    String?
}

model Location {
  id     Int    @id @default(autoincrement())
  name   String
  user   User   @relation(fields: [userId], references: [id])
  userId Int    @unique
}

model Item {
  id        Int       @id @default(autoincrement())
  user      User      @relation(fields: [userId], references: [id])
  userId    Int
  style     Style?
  images    String[]
  price     Int
  size      Size?
  category  Category?
  brand     Brand?
  colour    Colour?
  condition Int
}

model Size {
  id     Int    @id @default(autoincrement())
  name   String @unique
  item   Item?  @relation(fields: [itemId], references: [id])
  itemId Int?   @unique
}

model Colour {
  id     Int    @id @default(autoincrement())
  name   String @unique
  item   Item?  @relation(fields: [itemId], references: [id])
  itemId Int?   @unique
}

model Category {
  id     Int    @id @default(autoincrement())
  name   String @unique
  item   Item?  @relation(fields: [itemId], references: [id])
  itemId Int?   @unique
}

model Style {
  id     Int    @id @default(autoincrement())
  name   String @unique
  item   Item?  @relation(fields: [itemId], references: [id])
  itemId Int?   @unique
}

model Brand {
  id     Int    @id @default(autoincrement())
  name   String @unique
  item   Item?  @relation(fields: [itemId], references: [id])
  itemId Int?   @unique
}

Here is my DTO of item creation

export class CreateItemDto {
  @IsNotEmpty()
  style: string; // I should relate to style model (Vintage, Modern etc.)

  @IsNotEmpty()
  images: string[]; // Urls of the images

  @IsNotEmpty()
  @IsNumber()
  price: number;

  @IsNotEmpty()
  @IsString()
  size: string; // I should relate to size model (S,M,XL etc)

  @IsString()
  @IsNotEmpty()
  category: string;  

  @IsNotEmpty()
  @IsString()
  brand: string;

  @IsNotEmpty()
  @IsString()
  colour: string;

  @IsNotEmpty()
  @IsNumber()
  condition: number;
}

Here is my createItem function in service.

async createItem(dto: CreateItemDto, userId: number) {
    return await this.prisma.item.create({
      data: {
        userId,
        ...dto,
      },
    });
  }

I have tried to desrutize an dto and then add to the create but it cause more errors like The expected type comes from property 'category' which is declared here on type '(Without<ItemCreateInput, ItemUncheckedCreateInput> & ItemUncheckedCreateInput) | (Without<...> & ItemCreateInput)'.


Solution

  • The problem was to connect a models with relations.

    So instead of making it like this:

    async createItem(dto: CreateItemDto, userId: number) {
        return await this.prisma.item.create({
          data: {
            userId,
            ...dto,
          },
        });
      }
    

    I need to make it like this:

        async createItem(dto: CreateItemDto, userId: number) {
        const item = await this.prisma.item.create({
          data: {
            user: { connect: { id: userId } }, // Connect a records with realations
            condition: dto.condition,
            price: dto.price,
            description: dto.description,
            brand: { connect: { value: dto.brand } },
            category: { connect: { id: dto.categoryId } },
            colour: { connect: { value: dto.colour } },
            images: dto.images,
            size: dto.size,
            style: { connect: { value: dto.style } },
            gender: dto.gender,
          },
          select: {
            id: true,
            brand: true,
            category: true,
            price: true,
          },
        });
    
        return item;
      }