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

TypeScript type for EntityDTO with ManyToOne field is not correct #2414

Closed
dzcpy opened this issue Nov 14, 2021 · 2 comments · Fixed by #3389
Closed

TypeScript type for EntityDTO with ManyToOne field is not correct #2414

dzcpy opened this issue Nov 14, 2021 · 2 comments · Fixed by #3389

Comments

@dzcpy
Copy link

dzcpy commented Nov 14, 2021

Describe the bug
When JSONify entities which has unpopulated ManyToOne fields, the return result has wrong TypeScript types.

Stack trace

To Reproduce
Steps to reproduce the behavior:

  1. Given the following entities:
@Entity()
export class TeamMember extends BaseEntity<TeamMember, 'id'> {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'uuid_generate_v4()' })
  id: string;

  @ManyToOne({ entity: () => Team, onDelete: 'CASCADE', onUpdateIntegrity: 'CASCADE' })
  team: IdentifiedReference<Team>;
}
@Entity()
export class Team extends BaseEntity<Team, 'id'> {
  @PrimaryKey({ type: 'uuid', defaultRaw: 'uuid_generate_v4()' })
  id: string;

  @OneToMany({ entity: () => TeamMember, mappedBy: (teamMember) => teamMember.team, orphanRemoval: true, cascade: [Cascade.ALL] })
  members = new Collection<TeamMember>(this);
}
  1. Get the JSON verson of TeamMember record:
const teamMember = await orm.em.findOne(TeamMember, '{actual-team-member-id}');
const teamMemberJSON: EntityDTO<TeamMember> = teamMember.toJSON();
console.log(teamMemberJSON.team);
// 022b5aab-4a04-4c86-a9f0-e6c9748a7f74

teamMemberJSON.team's type now should be EntityDTO<Team>, but actually, it's a string id. So it causes some type errors

Expected behavior
Either set unpopulatd ManyToOne fields of JSONified object to string, or something like team: { id: '{actual-id}' };

Additional context

Versions

Dependency Version
node 17
typescript 4.4.4
mikro-orm 5.0.0-dev.439
your-driver postgresql
@B4nan
Copy link
Member

B4nan commented Nov 14, 2021

It can be PK or an object, depending of if you populate it. This information is available on the Loaded type, so even if we would have the EntityDTO type supporting it, you would basically erase it by explicitly defining your teamMemberJSON variable type (here it does not matter as you are not populating the relation).

Don't expec too much magic, those types will be always a bit wonky as we don't have the full context in many places. But in this particular example I hope we can handle it.

edit: Actually this might be problematic too, as I don't see a way to make the toJSON and others respect the Loaded context (this is Loaded but this.toJSON() won't pass the Loaded type to the EntityDTO, just the raw entity type). Seems like the problem is with the base entity, without it at least we see the type as EntityDTO<Loaded<...>>.

@B4nan
Copy link
Member

B4nan commented Aug 27, 2022

This will be finally resolved with the TS 4.8 update, including the inference for base entity methods. It will be slightly breaking (on type level) release for those who define custom toJSON methods - the signature will need to return EntityDTO<this> instead of EntityDTO<User> etc.

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