typescriptmikro-orm

MikroORM undefined property not returned


I'm trying and MikroORM and I like it but I have a situation that I do not userstand.

I have this small piece of code:

    const user = await appCtx.em.findOne(User, {email, accessToken})
    if (!user) {
        return
    }

    console.log('!* user before', user);
    user.accessToken = undefined
    console.log('!* user after', user);

which gives me (console.log output)

!* user before User {
  email: '12ab32f3-af94-4ef1-9c95-c5445a63fe78@api-test.com',
  name: 'Username',
  verifyToken: null,
  verifyTokenCreatedAt: null,
  verifiedAt: 2024-10-24T06:07:22.417Z,
  accessToken: '80b1b652-2f45-43db-8200-b9d003ad1ddb',
  createdAt: 2024-10-24T06:07:22.400Z,
  updatedAt: 2024-10-24T06:07:22.417Z,
  id: '3eab5128-5549-401d-88f6-98c2ff9f517c'
}
!* user after User {
  email: '12ab32f3-af94-4ef1-9c95-c5445a63fe78@api-test.com',
  name: 'Username',
  verifyToken: null,
  verifyTokenCreatedAt: null,
  verifiedAt: 2024-10-24T06:07:22.417Z,
  createdAt: 2024-10-24T06:07:22.400Z,
  updatedAt: 2024-10-24T06:07:22.417Z,
  id: '3eab5128-5549-401d-88f6-98c2ff9f517c'
}

My problem here is that I do not userstand why the accessToken property is missing from the 'user after' log. My tests would like to see that property returned with a null value. What am I missing?

For completeness, my Entity definition:

@Entity()
export class User {
    [OptionalProps]?: 'createdAt' | 'updatedAt'

    @PrimaryKey({type: "string"})
    id = crypto.randomUUID()

    @Property({type: "string", unique: true})
    email: string

    @Property({type: "string"})
    name: string

    @Property({type: "string", nullable: true})
    verifyToken?: string

    @Property({type: "Date", nullable: true})
    verifyTokenCreatedAt?: Date

    @Property({type: "Date", nullable: true})
    verifiedAt?: Date

    @Property({type: "String", nullable: true, index: true})
    accessToken?: string

    @Property({type: "Date"})
    createdAt = new Date();

    @Property({type: "Date", onUpdate: () => new Date() })
    updatedAt = new Date();

    constructor({email, name}: User) {
        this.email = email
        this.name = name
    }
}

and my initialisation:

export const orm = await MikroORM.init({
    entities: [User],

    dbName: mikroConfig.dbName,
    host: mikroConfig.host,
    user: mikroConfig.user,
    password: mikroConfig.password,

    logger: (message: string) => console.debug(message), // defaults to `console.log()`
})

Solution

  • The ORM won't convert undefined to null for you, and undefined values are omitted when you log the entity. The value is technically there, but it would be omitted once you serialize such entity, so its not very relevant to print it when console.logging.

    You can use explicit null if you want to see it (as well as have it in the serialized form/JSON), that's the only way currently. For that, you'd have to adjust the entity definition to allow the null value. Note that by doing so, reflect-metadata won't work anymore, since it cannot infer any union types, but I see you provide the type option explicitly already.

    // entity def
    accessToken?: string | null
    
    // usage
    user.accessToken = null
    

    It's up to you if you want to keep the optionality on type-level, accessToken: string | null will work too.