[1.2.2] Type error with Expo client plugin

Hey y'all, I'm getting this huge type error when I try to create the auth client on an Expo app. Here is my auth client code and I'm using the version 1.2.2 of better-auth and the latest version of expo-secure-store (14.0.1):
import * as SecureStore from "expo-secure-store";
import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_AUTH_PROXY_URL ?? "",
plugins: [
expoClient({
scheme: "app",
storagePrefix: "app",
storage: SecureStore,
}),
],
});
import * as SecureStore from "expo-secure-store";
import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
baseURL: process.env.NEXT_PUBLIC_AUTH_PROXY_URL ?? "",
plugins: [
expoClient({
scheme: "app",
storagePrefix: "app",
storage: SecureStore,
}),
],
});
Did anyone get this issue before?
No description
25 Replies
bekacru
bekacru2mo ago
can you share your tsconfig?
zenbb
zenbb2mo ago
im getting a similar error. Only happens when i bump to 1.2.2
import Constants from "expo-constants";
import * as SecureStore from "expo-secure-store";
import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";

import { env } from "~/env";

const scheme = Constants.expoConfig?.scheme as string;

export const authClient = createAuthClient({
disableDefaultFetchPlugins: true,
plugins: [
expoClient({
scheme,
storagePrefix: scheme,
storage: SecureStore,
}),
],
baseURL: env.EXPO_PUBLIC_BETTER_AUTH_CLIENT_URL,
});
import Constants from "expo-constants";
import * as SecureStore from "expo-secure-store";
import { expoClient } from "@better-auth/expo/client";
import { createAuthClient } from "better-auth/react";

import { env } from "~/env";

const scheme = Constants.expoConfig?.scheme as string;

export const authClient = createAuthClient({
disableDefaultFetchPlugins: true,
plugins: [
expoClient({
scheme,
storagePrefix: scheme,
storage: SecureStore,
}),
],
baseURL: env.EXPO_PUBLIC_BETTER_AUTH_CLIENT_URL,
});
@acme/tsconfig/base.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
/** Base Options */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "ES2022",
"lib": ["ES2022"],
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,

/** Keep TSC performant in monorepos */
"incremental": true,
"disableSourceOfProjectReferenceRedirect": true,
"tsBuildInfoFile": "${configDir}/.cache/tsbuildinfo.json",

/** Strictness */
"strict": true,
"noUncheckedIndexedAccess": true,
"checkJs": true,
"exactOptionalPropertyTypes": true,

/** Transpile using Bundler (not tsc) */
"module": "Preserve",
"moduleResolution": "Bundler",
"noEmit": true
},
"exclude": ["node_modules", "build", "dist", ".next", ".expo"]
}
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
/** Base Options */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "ES2022",
"lib": ["ES2022"],
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,

/** Keep TSC performant in monorepos */
"incremental": true,
"disableSourceOfProjectReferenceRedirect": true,
"tsBuildInfoFile": "${configDir}/.cache/tsbuildinfo.json",

/** Strictness */
"strict": true,
"noUncheckedIndexedAccess": true,
"checkJs": true,
"exactOptionalPropertyTypes": true,

/** Transpile using Bundler (not tsc) */
"module": "Preserve",
"moduleResolution": "Bundler",
"noEmit": true
},
"exclude": ["node_modules", "build", "dist", ".next", ".expo"]
}
tsconfig for expo
{
"extends": ["@acme/tsconfig/base.json"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
},
"jsx": "react-native",
"types": ["nativewind/types"],
"checkJs": false,
"moduleSuffixes": [".ios", ".android", ".native", ""]
},
"include": [
"src",
"*.ts",
"*.js",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts"
],
"exclude": ["node_modules"]
}
{
"extends": ["@acme/tsconfig/base.json"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
},
"jsx": "react-native",
"types": ["nativewind/types"],
"checkJs": false,
"moduleSuffixes": [".ios", ".android", ".native", ""]
},
"include": [
"src",
"*.ts",
"*.js",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts"
],
"exclude": ["node_modules"]
}
No description
EgeOnder
EgeOnderOP2mo ago
I have a monorepo so this is the tsconfig for the Expo app:
// apps/mobile/tsconfig.json

{
"extends": ["@app/tsconfig/base.json"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
},
"jsx": "react-native",
"types": ["nativewind/types"],
"checkJs": false,
"moduleSuffixes": [".ios", ".android", ".native", ""]
},
"include": [
"src",
"*.ts",
"*.js",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts"
],
"exclude": ["node_modules"]
}
// apps/mobile/tsconfig.json

{
"extends": ["@app/tsconfig/base.json"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"~/*": ["./src/*"]
},
"jsx": "react-native",
"types": ["nativewind/types"],
"checkJs": false,
"moduleSuffixes": [".ios", ".android", ".native", ""]
},
"include": [
"src",
"*.ts",
"*.js",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts"
],
"exclude": ["node_modules"]
}
And this is the extended base config:
// tooling/tsconfig/base.json

{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "ES2022",
"lib": ["ES2022"],
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,

"incremental": true,
"disableSourceOfProjectReferenceRedirect": true,
"tsBuildInfoFile": "${configDir}/.cache/tsbuildinfo.json",

"strict": true,
"noUncheckedIndexedAccess": true,
"checkJs": true,

"jsx": "react-jsx",

"module": "Preserve",
"moduleResolution": "Bundler",
"noEmit": true
},
"exclude": ["node_modules", "build", "dist", ".next", ".expo"]
}
// tooling/tsconfig/base.json

{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "ES2022",
"lib": ["ES2022"],
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,

"incremental": true,
"disableSourceOfProjectReferenceRedirect": true,
"tsBuildInfoFile": "${configDir}/.cache/tsbuildinfo.json",

"strict": true,
"noUncheckedIndexedAccess": true,
"checkJs": true,

"jsx": "react-jsx",

"module": "Preserve",
"moduleResolution": "Bundler",
"noEmit": true
},
"exclude": ["node_modules", "build", "dist", ".next", ".expo"]
}
Hey @zenbb , sorry to ping you directly but is there any progress on your part? I still get the same error so I was wondering if you've figured out what is wrong.
zenbb
zenbb2mo ago
Nah nothing on my end. Reverted back to 1.1.12 for now
'tonyyprints'
'tonyyprints'2mo ago
Any progress from your guys ends?
EgeOnder
EgeOnderOP3w ago
I added this code block as a temporary workaround to beat the type error for now
import type { BetterFetchPlugin } from "better-auth/react";
import * as SecureStore from "expo-secure-store";
import { expoClient as originalExpoClient } from "@better-auth/expo/client";
import { magicLinkClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const expoClient = (config: any) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const client = originalExpoClient(config);

return {
...client,
fetchPlugins: client.fetchPlugins.map((plugin) => ({
...plugin,
init: async (url: string, options?: RequestInit) => {
const result = await plugin.init(url, options);
return {
...result,
options: {
...result.options,
signal: result.options?.signal ?? undefined,
},
};
},
})) as BetterFetchPlugin[],
};
};

export const authClient = createAuthClient({
baseURL: getBaseUrl() + "/api/auth",
plugins: [
expoClient({
scheme,
storagePrefix: scheme,
storage: SecureStore,
}),
magicLinkClient(),
],
});
import type { BetterFetchPlugin } from "better-auth/react";
import * as SecureStore from "expo-secure-store";
import { expoClient as originalExpoClient } from "@better-auth/expo/client";
import { magicLinkClient } from "better-auth/client/plugins";
import { createAuthClient } from "better-auth/react";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const expoClient = (config: any) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const client = originalExpoClient(config);

return {
...client,
fetchPlugins: client.fetchPlugins.map((plugin) => ({
...plugin,
init: async (url: string, options?: RequestInit) => {
const result = await plugin.init(url, options);
return {
...result,
options: {
...result.options,
signal: result.options?.signal ?? undefined,
},
};
},
})) as BetterFetchPlugin[],
};
};

export const authClient = createAuthClient({
baseURL: getBaseUrl() + "/api/auth",
plugins: [
expoClient({
scheme,
storagePrefix: scheme,
storage: SecureStore,
}),
magicLinkClient(),
],
});
bekacru
bekacru3w ago
are you on latest version (1.2.4)? please check both better-auth and @better-auth/expo
Aziz
Aziz2w ago
now on 1.2.5 having similar type errors:
import { MMKV, Mode } from "react-native-mmkv";

import { createAuthClient } from "better-auth/react";
import { expoClient } from "@better-auth/expo/client";
import { Platform } from "react-native";

export const authStorage = new MMKV({
id: "auth-storage",
mode: Mode.MULTI_PROCESS,
});

export const authClient = createAuthClient({
baseURL: process.env.EXPO_PUBLIC_API_BASE_URL,
scheme: process.env.EXPO_PUBLIC_APP_SCHEME,
plugins: [
expoClient({ <-- "type 'Promise<string | undefined> is not assignable to type 'string | (() => string | undefined) | undefined"
scheme: process.env.EXPO_PUBLIC_APP_SCHEME,
storagePrefix: "auth",
storage: {
getItem: (key) => authStorage.getString(key) ?? null,
setItem: (key, value) => authStorage.set(key, value),
},
}),
],
});
import { MMKV, Mode } from "react-native-mmkv";

import { createAuthClient } from "better-auth/react";
import { expoClient } from "@better-auth/expo/client";
import { Platform } from "react-native";

export const authStorage = new MMKV({
id: "auth-storage",
mode: Mode.MULTI_PROCESS,
});

export const authClient = createAuthClient({
baseURL: process.env.EXPO_PUBLIC_API_BASE_URL,
scheme: process.env.EXPO_PUBLIC_APP_SCHEME,
plugins: [
expoClient({ <-- "type 'Promise<string | undefined> is not assignable to type 'string | (() => string | undefined) | undefined"
scheme: process.env.EXPO_PUBLIC_APP_SCHEME,
storagePrefix: "auth",
storage: {
getItem: (key) => authStorage.getString(key) ?? null,
setItem: (key, value) => authStorage.set(key, value),
},
}),
],
});
bekacru
bekacru2w ago
If you’re incase using better fetch as a direct dependency, update it to latest But I’ll take a look
Aziz
Aziz2w ago
Nope, these are the only two packages declared in my package.json:
@better-auth/expo@^1.2.5
better-auth@^1.2.5
@better-auth/expo@^1.2.5
better-auth@^1.2.5
But I do see different versions of better-fetch in my bun.lock
bekacru
bekacru2w ago
yeah it's probably a better fetch version mismatch I couldn't exactly reproduce the type issue in my end if I'm latest version of both /expo and the main better-auth pkg try removing node_modules and re-installing incase
Aziz
Aziz2w ago
Tried that, still have this issue It could be a bun issue, lemme try npm or yarn
luksch42
luksch422w ago
@Aziz any updates?
bekacru
bekacru2w ago
I can't reproduce it in my end. If both the expo and the main pacakge are on 1.2.5 and you don't have better-fetch with a differnt version making conflicts, it should work properly.
luksch42
luksch422w ago
better-fetch version looks ok hmm
bekacru
bekacru2w ago
are you on latest? if you can send me a POC would be happy to take a look :))
luksch42
luksch422w ago
@bekacru latest, monorepo & bun. Let me check that later, I have a deadline to hit with something else first.. Appreciate your help!
Aziz
Aziz2w ago
What is the expected better-fetch version?
bekacru
bekacru2w ago
1.1.18
luksch42
luksch422w ago
No type errors with [email protected] and an override for @better-fetch/[email protected] Errors from [email protected] with @better-fetch/[email protected] Types of property 'token' are incompatible. Related to feat: support async bearer token retrieval introduced in 1.1.18? The override is working fine by the way
bekacru
bekacru2w ago
can you check if 1.2.6-beta.3 version fixes it?
luksch42
luksch422w ago
It does, thanks!🤘🏻 What caused the problem? @bekacru
bekacru
bekacru7d ago
I think the expo plugin didn't have the latest version of better fetch
Forrest.Dev
Forrest.Dev2d ago
@bekacru im still seeing that better auth 1.2.5 has better fetch 1.1.17 version, which is causing the authClient to be untyped nvm it was because of the expo plugin i had it as a dep in one of the monorepo packages

Did you find this page helpful?