8

I created a NestJS and used TypeORM for the RDBMS(I used postgres in my project).

Post is an @Entity class, PostRepository is a Repository class for Post.

I was trying to create OnModuleInit service to initialize some data.

@Injectable()
export class PostsDataInitializer implements OnModuleInit {
  private data: Post[] = [
    {
      title: 'Generate a NestJS project',
      content: 'content',
    },
    {
      title: 'Create GrapQL APIs',
      content: 'content',
    },
    {
      title: 'Connect to Postgres via TypeORM',
      content: 'content',
    },
  ];

  constructor(private readonly postRepository: PostRepository) {}
  async onModuleInit(): Promise<void> {
    await this.postRepository.manager.transaction(async (manager) => {
      // NOTE: you must perform all database operations using the given manager instance
      // it's a special instance of EntityManager working with this transaction
      // and don't forget to await things here
      await manager.delete(Post, {});
      console.log('deleted: {} ');
      this.data.forEach(async (d) => await manager.save(d as Post));
      const savedPosts = await manager.find<Post>(Post);
      savedPosts.forEach((p) => {
        console.log('saved: {}', p);
      });
    });
  }
}

When starting up the application, I got the following error.


CannotDetermineEntityError: Cannot save, given value must be instance of entity class, instead object literal is given. Or you must specify an entity target to method call.

But the above save was accepting an instance of Post.

2 Answers 2

10

I think it is pretty much what the error says. You cannot pass literal objects to .save

  private data = [
    {
      title: 'Generate a NestJS project',
      content: 'content',
    },
    {
      title: 'Create GrapQL APIs',
      content: 'content',
    },
    {
      title: 'Connect to Postgres via TypeORM',
      content: 'content',
    },
  ].map(data => {
    const post = new Post();
    Object.assign(post, data);
    return post;
  })

the above might solve this.

Sign up to request clarification or add additional context in comments.

3 Comments

I used d as Post to cast it to Post, why this does not work. What is the difference between object literal and instance in typescript?
the difference isn't up to ts but to js. new Foo() objects will be instance of Foo, while a literal object that just has the shape of Foo won't. And TypeORM expect to work with instances of Foo
btw typecasting in strongly typed languages allow us to convert types. Since javascript is not strongly typed, the type assertion that you used will no longer exist at runtime. See this example
9

You can alternatively specify the target type as per the error message like so:

await manager.save(Post, d)

From the documentation of save() I see there is such a method as:

save<Entity, T extends DeepPartial<Entity>>(targetOrEntity: EntityTarget<Entity>, entity: T, options?: SaveOptions): Promise<T & Entity>;

nest version 9.1.8

2 Comments

Works better for me than the accepted answer
This answer worked well for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.