clerk / javascript

Official JavaScript repository for Clerk authentication
https://clerk.com
MIT License
1.18k stars 267 forks source link

`useUser` has a differently typed user object than `currentUser` and `clerkClient.users.getUser` #2176

Open kyldvs opened 1 year ago

kyldvs commented 1 year ago

Preliminary Checks

Reproduction / Replay Link

https://github.com/clerk/javascript/blob/main/packages/nextjs/src/app-router/server/currentUser.ts#L6

Publishable key

pk_test_1234567890

Description

When developing with Clerk the user objects returned from useUser() and currentUser() are different. Notably primaryEmailAddress and fullName exists in useUser().user, but doesn't exist in currentUser(). This inconsistency makes it more difficult to create shared utils and generally share things across different parts of our application.

The docs claim that these are the same User object, but that is not accurate.

The currentUser helper returns the User object of the currently active user. This is the same User object that is returned by the useUser hook.

The deviation occurs because useUser from clerk-react users clerk-types/UserResource: https://github.com/clerk/javascript/blob/main/packages/react/src/hooks/useUser.ts#L1

And currentUser uses clerk-backend/User: https://github.com/clerk/javascript/blob/main/packages/nextjs/src/app-router/server/currentUser.ts#L1

Expected behavior:

useUser().user and currentUser() should be the same type

Actual behavior:

They are not the same type

Environment

Not relevant and hard to get correct packages from a mono repo, but here it is for the root:

  System:
    OS: macOS 14.1
    CPU: (12) arm64 Apple M2 Max
    Memory: 53.19 MB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.3.1 - ~/.nvm/versions/node/v20.3.1/bin/node
    npm: 9.6.7 - ~/.nvm/versions/node/v20.3.1/bin/npm
    pnpm: 8.10.0 - ~/.nvm/versions/node/v20.3.1/bin/pnpm
  Browsers:
    Chrome: 119.0.6045.159
    Safari: 17.1
  npmPackages:
    @babel/preset-typescript: ^7.22.15 => 7.22.15
    @commitlint/cli: ^17.6.7 => 17.6.7
    @commitlint/config-conventional: ^17.6.7 => 17.6.7
    @knnlabs/configs: workspace:* => 0.0.0
    @knnlabs/eslint-config-custom: workspace:* => 0.0.0
    @trivago/prettier-plugin-sort-imports: ^4.2.0 => 4.2.0
    @turbo/gen: ^1.10.12 => 1.10.12
    @types/jest: ^29.5.4 => 29.5.4
    bun: ^1.0.3 => 1.0.3
    eslint: ^8.46.0 => 8.50.0
    husky: ^8.0.3 => 8.0.3
    jest: ^29.6.4 => 29.6.4
    lint-staged: ^13.2.3 => 13.2.3
    prettier: ^3.0.0 => 3.0.0
    prettier-plugin-prisma: ^5.0.0 => 5.0.0
    turbo: ^1.10.16 => 1.10.16
panteliselef commented 1 year ago

Hey @kyldvs, those are 2 different types and should not be treated as a "common" interface.

firstName exists for both types. You are correct primaryEmailAddress only exists for the client one, as a workaround you can depend on primaryEmailAddressId and the emailAddresses array which both exist in both types.

F.e.

primaryEmailAddress = emailAddresses.find(({ id }) => id === primaryEmailAddressId)
kyldvs commented 1 year ago

Thanks for the fast response! I guess at a minimum this is an error in the documentation, but I am hoping this can be updated to be the same interface for both.

Right now it's annoying to share some utilities working with Clerk users across server & client because of the different types (in a graphql context, not SSR, otherwise I could just use the same hooks). Is that possible or is it intentional that these types are different?


The error in the documentation would be that the currentUser() page claims to return a User object, and that user page claims to have properties like fullName and primaryEmailAddress (also to avoid potential confusion you mention firstName, but I have been talking about only fullName in this issue). But the currentUser() function does not return an object with those properties.

Jhinger commented 12 months ago

Also experienced this issue while trying to get a users' organizationMemberships from currentUser - the User type returned from currentUser and useUser are not the same and the docs should be updated to reflect that (or ideally as @kyldvs mentioned the interfaces should be updated to match).

https://clerk.com/docs/references/nextjs/current-user

ubersan commented 11 months ago

It would be indeed nice to know if it's planned to also provide the additional properties (e.g. orgs) in the server-side variant currentUser.

thinkjrs commented 10 months ago

I also ran into this today and would love to see the interfaces match if possible! @panteliselef 🙏 Thanks for the solution, this works fine for now!

qublaidev commented 6 months ago

I tried to pass the user coming from useUser() but I get the following error:

Type 'UserResource' is missing the following properties from type 'UserResource': passkeys, createPasskey

Upon further investigation I stumbled upon the problem that UserResource type used in useUser() does not include passkeys and createPasskey that is coming from UserResource at @clerk/types

danajerban commented 6 months ago

while UserResource can be found from @clerk/types.. where can User be found? - the type coming from {currentUser}: '@clerk/nextjs/server' for example

@panteliselef

Thanks

dimkl commented 6 months ago

@danajerban The User object can be found in import type { User } from '@clerk/nextjs/server'

the-simian commented 2 months ago

I am experiencing a similar, and possible related issue in clerk-expo I've logged the issue here: https://github.com/clerk/javascript/issues/4105

Short version: The UserResource that is in @clerk/types doesn't match the user object returned from useUser hook. Its missing Web3 stuff. Some of which is seemingly still being deployed in new features. This is from just a few hours ago: https://github.com/clerk/javascript/pull/4103

Edit: This is what is causing the break in my 'related' issue