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

qb.getResultAndCount() fails on execution, if Entity field type uses TS allias #5221

Closed
5 tasks done
DenisLutsky opened this issue Feb 8, 2024 · 4 comments
Closed
5 tasks done

Comments

@DenisLutsky
Copy link

DenisLutsky commented Feb 8, 2024

Describe the bug

...
const qb = this.orm.em.createQueryBuilder(UserEntity, 'user');
const [items, count] = await qb.select('*').getResultAndCount();
...

Code like this example will fail with the exception posted below if the field of entity using named type alias instead of notation with a pipe and the recond in DB table has value that is not NULL

type Nullable<T> = T | null;

@Property({ columnType: 'varchar', length: 50, nullable: true })
public firstName!: string | null; // works fine

@Property({ columnType: 'varchar', length: 50, nullable: true })
public firstName!: Nullable<string>; // fails and fails only with QB, em.find working fine
ValidationError: Trying to set UserEntity.firstName of type 'object' to 'John' of type 'string'
    at Function.fromWrongPropertyType (C:\projects\_\node_modules\@mikro-orm\core\errors.js:23:16)
    at EntityValidator.validateProperty (C:\projects\_\node_modules\@mikro-orm\core\entity\EntityValidator.js:73:48)
    at C:\projects\_\node_modules\@mikro-orm\core\entity\EntityValidator.js:25:35
    at Array.forEach (<anonymous>)
    at EntityValidator.validate (C:\projects\_\node_modules\@mikro-orm\core\entity\EntityValidator.js:14:20)
    at SqlEntityManager.merge (C:\projects\_\node_modules\@mikro-orm\core\EntityManager.js:1147:22)
    at SqlEntityManager.map (C:\projects\_\node_modules\@mikro-orm\core\EntityManager.js:1123:21)
    at QueryBuilder.getResultList (C:\projects\_\node_modules\@mikro-orm\knex\query\QueryBuilder.js:664:36)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 0) - [32/14]

The problem appeared after updating mikro-orm to version 6.x, on previous (4, 5) there were no problems with that

Reproduction

  1. Setup NestJS application
  2. Create TS type alias type Nullable<T> = T | null;
  3. Create entity class
    eg.
@Entity({ tableName: 'users' })
export class UserEntity extends BaseEntity {
  @PrimaryKey()
  public userId!: number;

  @Property({ columnType: 'varchar', length: 50, nullable: true })
  public firstName!: Nullable<string>;

  @Property({ columnType: 'varchar', length: 50, nullable: true })
  public lastName!: Nullable<string>;

  @Property({ columnType: 'varchar', length: 320, unique: true })
  public email!: string;

  @Property({ columnType: 'text' })
  public password!: string;

  @Property({ columnType: 'bool', default: false })
  public isDeleted!: boolean;

  @Property({ columnType: 'timestamp', defaultRaw: 'current_timestamp' })
  public createdAt!: Date;

  @Property({ columnType: 'timestamp', defaultRaw: 'current_timestamp', onUpdate: () => new Date() })
  public updatedAt!: Date;

  public [OptionalProps]?: 'userId' | 'isDeleted' | 'createdAt' | 'updatedAt';
}

  1. Inject MikroORM instanc with PG driver using public constructor(private readonly orm: MikroORM<PostgreSqlDriver>) {}
  2. Build query builder request
    e.g.
...
const qb = this.orm.em.createQueryBuilder(UserEntity, 'user');
const [items, count] = await qb.select('*').getResultAndCount();
...

What driver are you using?

@mikro-orm/postgresql

MikroORM version

6.1.0

Node.js version

node v20.10.0, npm 10.2.3

Operating system

Windows 11

Validations

@B4nan
Copy link
Member

B4nan commented Feb 8, 2024

Using ts-morph I guess? That's the important part here that you skipped from the report.

Setup NestJS application

If this is your first step to set up a minimal repro, you don't understand what a minimal repro means :] You don't need web server to reproduce anything.

@B4nan
Copy link
Member

B4nan commented Feb 8, 2024

What TS version are you using? I am not able to reproduce this with 5.3. On the other hand, I know quite well what's happening and I can fix that, it's just not reproducible on my end.

@B4nan B4nan closed this as completed in d6b93be Feb 8, 2024
@DenisLutsky
Copy link
Author

Thank you for fix.

I'm sorry for bad repro steps.

No, I don't use ts-morph
TS version "typescript": "^5.3.3"

@B4nan
Copy link
Member

B4nan commented Feb 8, 2024

Hmm, then it needs to be caused by SWC, their reflect-metadata support is pretty broken, so many differences...

Anyway, the fix I did should cover this too, the property type validation is now limited only to a set of known types, and those don't include object.

You can also get around such problems by specifying the type explicitly:

@Property({ type: 'string', length: 50, nullable: true }) // strings are by default mapped to varchar
public firstName!: Nullable<string>;

And one more note - your entity definition is a bit wrong, since you use columnType and length next to each other - the length has no effect there, you need to include it in the columnType as that is always used as is, without any postprocessing.

@Property({ columnType: 'varchar(50)', nullable: true })
public firstName!: Nullable<string>;

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

No branches or pull requests

2 participants