Search code examples
javascripttypescriptcontrollernestjsdto

NestJS: Cannot get nested object in console.log. Error: Property x does not exist on type Dto


for some reason I cannot get the nested object to display in my console log. Been trying to look for a solution for about a day now.

Here is my JSON:

{
   "data": {
      "assets": [
              {
                 "asset_name": "Image1.jpg",
                 "asset_type": "photo",
                 "is_featured": true,
                 "asset_id": "alksjd78987120-kjahsdkjahsd61238-kjahsdkjahsjkdh",
                 "action": "delete"
              },
              {
                  "asset_name": "Image2.jpg",
                  "asset_type": "photo",
                  "action": "add"
              }
       ]
     }
   }

I am trying to display console.log(data.assets); in my controller file to check it before passing it to the service file but I keep on getting the error Property 'assets' does not exist on type 'DataDto'.

Here is my DataDto.ts

export class CreateAssetsDto {
   @IsString()
   @IsOptional()
   asset_id: string;

   @ApiProperty()
   @IsString()
   asset_name: string;

   @ApiProperty({
       enum: Action
   })
   @IsEnum(Action)
   @IsNotEmpty()
   action: Action;

   @ApiProperty()
   @IsString()
   asset_type: string;

   @ApiProperty()
   @IsBoolean()
   @IsOptional()
   is_featured: boolean;
}
export class AssetsArrayDto {
   @ValidateNested()
   @Type(() => CreateAssetsDto)
   assets: CreateAssetsDto[];
}

export class DataDto {
   @ValidateNested()
   @Type(() => AssetsArrayDto)
   data: AssetsArrayDto;
}

Here is my controller.ts

@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'))
@UsePipes(new ValidationPipe({ transform: true }))
@Put(':id')
async uploadAssets(
   @Request() req,
   @Param('id') campaignId: string,
   @Body() data: DataDto) {
   try {
     console.log("Data Check");
     console.log(data);

     const { assets } = data;
     console.log(data.assets[0].asset_name);
     console.log(JSON.stringify(data, null, 2));

     const a = JSON.parse(JSON.stringify(data));

     console.log(a)
     console.log(assets)

     return {
       statusCode: HttpStatus.OK,
       message: data,
     };

   } catch (error) {
     Logger.log('Validation Error: ');
     Logger.log(error);
     throw new BadRequestException(error);
   }
 }
 }

Do I need to do something that I missed? Based on the error it seems like my data object is not reading assets as part of it even though I indicated it in the DTO.

Also, when I do console.log(data) this is what I get:

Data Check
DataDto {
 data: AssetsArrayDto { assets: [ [CreateAssetsDto], [CreateAssetsDto] ] }
}

Solution

  • You've told Typescript that DataDto has a property called data that is of type AssetsArrayDto. You've told JavaScript to pull assets off of an instance of DataDto. DataDto does not have an assets property, so Typescript is warning you that what you're trying to do is incorrect. You'd need something like

    @ApiBearerAuth()
    @UseGuards(AuthGuard('jwt'))
    @UsePipes(new ValidationPipe({ transform: true }))
    @Put(':id')
    async uploadAssets(
       @Request() req,
       @Param('id') campaignId: string,
       @Body() data: DataDto) {
       try {
         console.log("Data Check");
         console.log(data);
    
         const { assets } = data.data;   // <-- notice the .data here
         console.log(data.assets[0].asset_name);
         console.log(JSON.stringify(data, null, 2));
    
         const a = JSON.parse(JSON.stringify(data));
    
         console.log(a)
         console.log(assets)
    
         return {
           statusCode: HttpStatus.OK,
           message: data,
         };
    
       } catch (error) {
         Logger.log('Validation Error: ');
         Logger.log(error);
         throw new BadRequestException(error);
       }
     }