Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending BaseEntity causes underlying methods to return types of BaseEntity instead of their higher order types. #9215

Open
chevsunpower opened this issue Jul 19, 2022 · 3 comments

Comments

@chevsunpower
Copy link

chevsunpower commented Jul 19, 2022

Issue Description

If I create a class and extend BaseEntity I get the active record style of interaction as expected. However the methods on the base class only return type BaseEntity. For example, here's a simple active record entity:

class Project extends BaseEntity {

  @PrimaryGeneratedColumn("uuid")
  id: string;
  
  @Column({ nullable: true })
  comment: string;

}

Now if I save a new entity it will save it as expected:

await Project.save({ comment: "hello, typeorm" });

However, if I then try to get the returned entity and read it's ID it will complain:

const newProject = await Project.create({ comment: "hello, typeorm" });
console.log(newProject.id); // does not work

Here we get Property 'id' does not exist on type 'BaseEntity'. I have to manually cast the generic save method to rectify this, which kind of defeats the point of active record simplicity a little bit.

const newProject = await Project.create<Project>({ comment: "hello, typeorm" });
console.log(newProject.id); // this works

Expected Behavior

I would expect the save method in this case to return an instance of Project.

My Environment

Dependency Version
Operating System
Node.js version 16.14.2
Typescript version 4.7.4
TypeORM version 0.3.7

Relevant Database Driver(s)

DB Type Reproducible
aurora-mysql no
aurora-postgres no
better-sqlite3 no
cockroachdb no
cordova no
expo no
mongodb no
mysql no
nativescript no
oracle no
postgres yes
react-native no
sap no
spanner no
sqlite no
sqlite-abstract no
sqljs no
sqlserver no

Are you willing to resolve this issue by submitting a Pull Request?

  • ✖️ Yes, I have the time, and I know how to start.
  • ✖️ Yes, I have the time, but I don't know how to start. I would need guidance.
  • ✖️ No, I don’t have the time, but I can support (using donations) development.
  • ✅ No, I don’t have the time and I’m okay to wait for the community / maintainers to resolve this issue.
@chevsunpower
Copy link
Author

Maybe it's not easy to get the type from static class methods without a manually specified generic but at the very least I'd love to be able to specify the type on the class itself.

class Project extends BaseEntity<Project> {
  /* ... */
}

At least then we'd only have to specify it once instead of every time you use a static method on the class.

@lucas-labs
Copy link

I'm getting the same error.

image

It's returning the wrong type, it should return the entity's class.

Maybe it's not easy to get the type from static class methods without a manually specified generic but at the very least I'd love to be able to specify the type on the class itself.

I'm pretty sure It was working ok in version 0.2.x, the code in the screenshot above wasn't showing any errors at least.

This is how it was defined back in 0.2:

static create<T extends BaseEntity>(this: ObjectType<T>, entityOrEntities?: any): T {
return (this as any).getRepository().create(entityOrEntities);
}

Now it has been changed:

static create<T extends BaseEntity>(
this: { new (): T } & typeof BaseEntity,
entityOrEntities?: any,
) {
return this.getRepository<T>().create(entityOrEntities)
}

@olivierlacan
Copy link

This is a bit of a bummer because we were hoping to use await SomeEntity.create(entityProperties).save() directly in test setup logic but we're having to fall back to this instead to get proper typings:

const instance = new SomeEntity(entityProperties);
await instance.save()
// => Promise<SomeEntity>

Whereas this sadly doesn't work:

await SomeEntity.create(entityProperties).save();
// => Promise<BaseEntity>

@AlexMesser it looks like this typing regression was introduced by this bug fix, any chance you could give it a look?

It looks like the type union added here is blocking the BaseEntity descendant from showing up as the return type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants