skip to Main Content

I just started a new NestJS api using Prisma instead of Typeorm and there’s one aspect that’s not behaving as expected. Typeorm automatically casts strings to numbers that correspond to datatypes specified in the DTO or Entity. Prisma doesn’t do that and I get the following error.

Argument weight_per_pallet: Got invalid value '1847' on prisma.updateOneProduct. Provided String, expected Int

here is an excerpt of my DTO.

export class CreateProductDto {
  @ApiProperty()
  name: string;

  @ApiProperty()
  product_code: string;

  @ApiProperty()
  cartons_per_pallet: number;

  @ApiProperty()
  weight_per_pallet: number;
}

The only way this works correctly is that I must set the input type to number in my html form. When I was using TypeORM, It did not matter which input type I used. Why doesn’t prisma automatically cast to the proper datatype? Is there a way to automatically do this so I don’t have to modify dozens of inputs in my html?

  <!-- this works -->
  <input matInput id="weight_per_pallet" type="number">
  
  <!-- this does not -->
  <input matInput id="weight_per_pallet">

2

Answers


  1. I would use a Pipe as the documentation say:

    Pipes have two typical use cases:
    transformation: transform input data to the desired form (e.g., from string to integer)
    validation : evaluate input data and if valid, simply pass it through unchanged; otherwise, throw an exception

    Refer to Pipes documentation for more

    Login or Signup to reply.
  2. If you want to cast the variable to number type, use the Pipe.

    Here’s the example

    // Expand the type of weight_per_pallet from number to number | string
    export class CreateProductDto {
      @ApiProperty()
      name: string;
    
      @ApiProperty()
      product_code: string;
    
      @ApiProperty()
      cartons_per_pallet: number;
    
      @ApiProperty()
      weight_per_pallet: number | string;
    }
    
    // Below code is to transform the DTO using pipe
    @Injectable()
    export class TransformDtoPipe implements PipeTransform {
      transform(createRequest: CreateProductDto): CreateProductDto {
        const { weight_per_pallet } = createRequest;
        
        if (typeof weight_per_pallet === 'string') {
          createRequest.weight_per_pallet = Number(weight_per_pallet)
        }
        
        return createRequest;
      }
    }
    
    // And use above pipe on your controller
    @Injectable()
    export class YourController {
      constructor(private readonly yourService: YourService) {}
      
      async create(@Body(TransformDtoPipe) createRequest: CreateProductDto) {
        ...
      }
    }
    

    By Expanding your dto (change type of weight_per_pallet from number to number | string for receiving number and string types), and using pipe transform, you can convert string to number automatically.

    Important is, you must type app.useGlobalPipes(new ValidationPipe({ transform: true, whitelist: true })) on your main.ts. That code is for using pipes on your project.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search