Error: Unable to cast value to an array due to validation failure

I'm currently working on integrating Typegoose with GrqphQL, MongoDB, and Nest.js for a project. My goal is to create a mutation that will allow users to create a post. I have set up the model, service, and resolver for a simple Post. However, when I attempt to run the mutation to create a Post, I encounter the following error:

PostModel validation failed: sections: Cast to Array failed for value:

[
  [Object: null prototype] {
    title: 'section 1',
    body: [ 'section test lalal' ],
    code: [ "console.log('hello world!)" ],
    image: [ 'kanow.svg' ]
  }
]

at path "sections"

I have tried using ref and itemsRefs for both class and string values. You can find more information about this in the Typegoose arrayProp documentation. After creating a new PostModel and logging every property, I noticed that the sections array is empty, even though it shouldn't be. The JSON within postInput looks like this:

[Object: null prototype] {
  title: 'refactored post',
  image: 'rest.jpg',
  tags: [ 'ref, ref' ],
  sections: [
    [Object: null prototype] {
      title: 'section 1',
      body: [Array],
      code: [Array],
      image: [Array]
    }
  ]
}

Based on this JSON data, everything seems correct, so this should not be the cause of the error.

I would appreciate any insights on what I might be doing wrong and why it's not working as expected. Below you'll find some relevant code snippets. Feel free to ask if you need any additional information in the comments.

GraphQL mutation:

mutation {
  createPost(postInput: {
    image: "rest.jpg",
    title: "refactored post"
    tags: ["ref, ref"]
    sections: [{
      title: "section 1"
      body: ["section test lalal"]
      code: ["console.log('hello world!)"]
      image: ["kanow.svg"]
    }]
  }) {
    _id
    title
    tags
    sections {
      title
      body
      code
      image
    }
  }
}

post.service.ts:

@Injectable()
export class PostsService {
    constructor(@InjectModel(PostModel) private readonly postModel: ReturnModelType<typeof PostModel>) {
    }

    async create(postInput: CreatePostInput): Promise<DocumentType<PostModel>> {
        const createdPost: DocumentType<PostModel> = new this.postModel(postInput);
        return await createdPost.save();
    }
 ...
}

post.model.ts:

@ObjectType()
export class PostModel {
    @Field(() => ID)
    readonly _id: ObjectId;

    @Field()
    @prop({required: true})
    title: string;

    @Field()
    @prop({nullable: true})
    image: string;

    @Field(() => [String])
    @arrayProp({items: String})
    tags: string[];

    @Field(() => [SectionModel])
    @arrayProp({ref: 'SectionModel'})
    sections: Ref<SectionModel>[];
}

section.model.ts:

@ObjectType()
export class SectionModel {
  @Field()
  @prop({ required: true })
  title: string;

  @Field(() => [String])
  @arrayProp({ items: String })
  body: string[];

  @Field(() => [String])
  @arrayProp({ items: String })
  code: string[];

  @Field(() => [String])
  @arrayProp({ items: String })
  image: string[];
}

create-post.input.ts:

@InputType()
export class CreatePostInput {
  @Field()
  readonly title!: string;

  @Field()
  readonly image!: string;

  @Field(() => [String])
  readonly tags!: string[];

  @Field(() => [CreateSectionInput])
  readonly sections!: CreateSectionInput[];
}

UPDATE 1

I found that passing an empty array inside the sections body allows me to create a post without any issues. Here's an example query:

mutation {
  createPost(postInput: {
    image: "newly created.jpg",
    title: "newly created"
    tags: ["newly created, ref"]
    sections: []
  }) {
    _id
    image
    title
    tags
    sections {
      title
      body
      code
      image
    }
  }
}

Answer №1

After some research, I realized that using Ref<> to declare nested documents was not the right approach. Instead, you need to utilize items and specify the correct Typegoose model class. While the documentation initially states that items are intended only for primitive types, it later clarifies that you can also use them with Typegoose classes (such as SectionModel.ts). Below is an example that effectively resolves this issue.

post.model.ts:

@ObjectType()
export class PostModel {
  @Field(() => ID)
  readonly _id: ObjectId;

  @Field()
  @prop({required: true})
  title: string;

  @Field()
  @prop({nullable: true})
  image: string;

  @Field(() => [String])
  @arrayProp({items: String})
  tags: string[];

  @Field(() => [SectionModel])
  @arrayProp({items: SectionModel})
  sections: SectionModel[];
}

section.model.ts:

@ObjectType()
export class SectionModel {
  @Field(() => ID)
  readonly _id: ObjectId;

  @Field()
  @prop({ required: true })
  title: string;

  @Field(() => [String])
  @arrayProp({ items: String })
  body: string[];

  @Field(() => [String])
  @arrayProp({ items: String })
  code: string[];

  @Field(() => [String])
  @arrayProp({ items: String })
  image: string[];
}

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

Issue with Angular custom tag displaying and running a function

I have created a custom HTML tag. In my next.component.ts file, I defined the following: @Component({ selector: 'nextbutton', template: ` <button (click) = "nextfunc()">Next</button> ` }) export class NextComponent{ nextfunc( ...

Problem with Jasmine in Angular 5 within Visual Studio Code

I am completely new to Angular 5 Unit testing and facing some challenges. Despite installing all @types/jasmine, I am encountering errors in my spec.ts file such as 'describle is not a name' and 'jasmine.createSpyObj does not exist on the ty ...

Automatically dismiss modal upon submission

In the process of implementing a CRUD operation, I am trying to automatically close the modal upon submission. Using data-dismiss on the submit button only closes the modal without executing the functionality. What I need is for the functionality to execut ...

Using Firebase with Angular 4 to fetch data from the database and show it in the browser

Currently diving into Angular 4 and utilizing Firebase database, but feeling a bit lost on how to showcase objects on my application's browser. I'm looking to extract user data and present it beautifully for the end-user. import { Component, OnI ...

The duration of recorded audio in JavaScript is unclear

I managed to successfully create a structure for recording and downloading audio files. However, I'm facing an issue where the final downloaded file has an unknown duration. Is there any way to solve this problem?? Here is my Typescript code snippet: ...

After importing this variable into index.ts, how is it possible for it to possess a function named `listen`?

Running a Github repository that I stumbled upon. Regarding the line import server from './server' - how does this API recognize that the server object has a method called listen? When examining the server.ts file in the same directory, there is ...

The component is no longer able to locate the imported element when it is being shared

Recently, I imported a component into the shared module in order to use it across 2 different modules. However, upon recompiling the app, an error message appeared stating that the jodit-editor, which is utilized by the shared component, is not recognized ...

Setting up only two input fields side by side in an Angular Form

I'm fairly new to Angular development and currently working on creating a registration form. I need the form to have two columns in a row, with fields like Firstname and Lastname in one row, followed by Phone, Email, Password, and Confirm Password in ...

Assign a specific value to the sub-component within the grid using Angular 2+

Incorporating Angular 8 and TypeScript into my project, I have a grid that consists of various internal components, one being <ng-select/>. The data binding takes place in the child component during onInit. Upon loading and initialization of the dat ...

Displaying notification in Ionic 2

Whenever I click on the register button, if I fill out all the fields I am taken to the regsuccess page. Otherwise, I receive a message saying to fill in all required fields. However, I want to display an alert message using Ionic2 and TypeScript. HTML: ...

Encountered a server issue (500 Internal Server Error) when attempting to send a POST

I have been working on a social media app project using React and MongoDB. However, every time I try to register a user, I encounter a POST error in the console. I have reviewed both my client-side and server-side code, but I am still unable to successfull ...

Having trouble pushing data to a GraphQL database from my Next.js application

I am currently working on developing a Reddit-like platform. To simplify the process, I have integrated SQL with graphQL using Stepzen for endpoints. Below is the code snippet of my Post Box component for the site, which includes graphQL mutations.ts and q ...

What methods are available to rapidly test Firebase functions?

While working with Typescript on firebase functions, I have encountered challenges in testing and experimenting with the code. Despite using the Lint plugin to identify errors without running the code, I am struggling to run the code and view the output. ...

What is the best way to implement bypassSecurityTrustResourceUrl for all elements within an array?

My challenge is dealing with an array of Google Map Embed API URLs. As I iterate over each item, I need to bind them to the source of an iFrame. I have a solution in mind: constructor(private sanitizer: DomSanitizationService) { this.url = sanitizer. ...

What is the best way to pass a variable from a class and function to another component in an Angular application?

One of the components in my project is called flow.component.ts and here is a snippet of the code: var rsi_result: number[]; @Component({ selector: 'flow-home', templateUrl: './flow.component.html', styleUrls: ['./flow.comp ...

React Component - Element with an undefined value

When I tried implementing an Ionic Modal as a React Component, I encountered the following error message: Type '({ onClose, tipo }: PropsWithChildren<{ onClose: any; tipo: number; }>) => Element | undefined' is not assignable to type & ...

What are some ways to resolve this console error: "TS2307: Could not locate module '@components/common/ButtonBlock' or its corresponding type declarations."

While the project is running smoothly, I am noticing a multitude of errors appearing in the console of VS Code. How can I eliminate these error messages? It seems to be related to TypeScript. Additionally, I am encountering an error in the browser as well ...

Tips for generating a fixed-length array from multiple arrays with different lengths, focusing on selecting items from each array according to their significance

In order to create a quiz, I am looking to extract 'questions' from various 'topic' arrays. These topics are selected based on the user's preference and are used to populate a question bank for a 20-question quiz. The topics rated ...

The JSON object, which has been converted into a string and sent over the network,

Attempting to set up a websocket server using TypeScript in Node.js, the following code was used: ws.on('message', (msg: string) => { console.log("got message:" + msg); const m = JSON.parse(msg); console.log(m); ...

Assign a property to an object following the execution of the query

I am currently utilizing node express to achieve a specific functionality. I encountered an issue while attempting to populate a field with data from another field. To resolve this problem, I decided to retrieve the value from another query and then assign ...