Why is the user_id optional?

When looking at the Auth0 Management API documentation, user_id on a user is optional?

Why is that the case - will a user not always have a user_id?

(this is giving some issues when implementing strict null check in typescript)

Hi @alexab,

You are referring to the get_users endpoint, this is a search API endpoint. You can search for whatever criteria you want here. A user always has a user_id, but that doesn’t mean you have to search for such; you can search for any criteria you want, i.e. email address, phone number, any other attribute.

(this is giving some issues when implementing strict null check in typescript)

Not clear why this would be. You would be defining a “user search” type, not a “user” type in this case, right? A “user search” should not have a user_id required.

Hi @mathiasconradt - thanks for your quick reply.

I understand that the link refers to searching for a user. But let’s say that we do find a user - this user will always have a user_id property - correct?

If you agree on this, the typings in theAuth0 DefinitelyTyped repo are incorrect. I know the typings are not maintained by Auth0, but the package has almost 14.000 weekly downloads on NPM(!)

Actually, in the typings definition all properties on the user are optional…

export interface UserData<A = AppMetadata, U=UserMetadata> {
  email?: string;
  username?: string;
  email_verified?: boolean;
  verify_email?: boolean;
  user_id?: string;
  blocked?: boolean;
  nickname?: string;
  picture?: string;
  password?: string;
  phone_number?: string;
  phone_verified?: boolean;
  given_name?: string;
  family_name?: string;
  name?: string;
  user_metadata?: U;
  app_metadata?: A;
}

Yes, this is correct.

Not sure why it’s optional. Maybe the intention was to keep it flexible, such as being able to pass such object (especially UserData as opposed to User) to the search, where user_id is optional.

I noticed in your link that there are two interfaces defined: User and UserData, which are almost similar but not exactly. Seems like UserData is a subset of User.

Ok. I will draft a PR for the repo then.

Typescript supports the Partial operator, if you wan’t all properties to be optional (a good usecase here i think).

Do you know of any other properties that are always present, i.e. not optional?

Thanks in advance.

created_at and updated_at in User (not UserData) should always be there. Everything else is optional.

email must remain optional because it’s possible that one comes via Passwordless authentication (SMS) where only a phone number is present.

What about app_metadata and user_metadata? Are they not there always, and just being empty objects if nothing defined?

From a typescript perspective, I don’t need to know if the value is an empty string for example. If the property is always there, it should not be optional. I hope that makes sense :slight_smile:

app_metadata and user_metadata isn’t always there (= it is not there but empty). It can be entirely non-existent.

1 Like

@alexab Did you ever submit a PR? I just ran into this exact issue and see that user_id is still optional.

No I’m sorry - never got to issue the PR. Don’t remember my work-around but if you share more code, maybe I can help?

I’ve been using two workarounds. The first is to throw an Error. The Typescript compiler is smart enough to know the subsequent block of code can’t be reached if user_id is undefined.

if (!user.user_id) {
    throw new Error('undefined user_id');
}
auth0.updateAppMetadata({ id: user.user_id }, {...});

The other option is to cast.

auth0.updateAppMetadata({ id: user.user_id as string }, {...}); 

The difference seems a matter of style.