fix(client): preserve null in useSession().data type with throw:true (#9787)

This commit is contained in:
Maxwell
2026-07-16 06:55:23 +00:00
committed by GitHub
parent 502a262ff2
commit ae78109118
6 changed files with 102 additions and 12 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"better-auth": patch
---
Fixes an issue where `useSession({ throw: true })` incorrectly excluded `null` from its `data` type.
@@ -393,6 +393,99 @@ describe("type", () => {
>();
});
/**
* @see https://github.com/better-auth/better-auth/issues/9781
*/
describe("useSession().data with nullable types", () => {
it("useSession().data should be nullable with `throw:true` - react", () => {
const client = createReactClient({
plugins: [testClientPlugin()],
baseURL: "http://localhost:3000",
fetchOptions: {
throw: true,
customFetchImpl: async (url, init) => {
return new Response();
},
},
});
type UseSessionReturn = ReturnType<typeof client.useSession>;
type DataField = UseSessionReturn["data"];
expectTypeOf<null>().toMatchTypeOf<DataField>();
});
it("useSession().data should be nullable with `throw:true` - vue", () => {
const client = createVueClient({
plugins: [testClientPlugin()],
baseURL: "http://localhost:3000",
fetchOptions: {
throw: true,
customFetchImpl: async (url, init) => {
return new Response();
},
},
});
const session = client.useSession();
type DataField = (typeof session)["value"]["data"];
expectTypeOf<null>().toMatchTypeOf<DataField>();
});
it("useSession().data should be nullable with `throw:true` - solid", () => {
const client = createSolidClient({
plugins: [testClientPlugin()],
baseURL: "http://localhost:3000",
fetchOptions: {
throw: true,
customFetchImpl: async (url, init) => {
return new Response();
},
},
});
type UseSession = ReturnType<typeof client.useSession>;
type UseSessionReturn = ReturnType<UseSession>;
type DataField = UseSessionReturn["data"];
expectTypeOf<null>().toMatchTypeOf<DataField>();
});
it("useSession().data should be nullable with `throw:true` - svelte", () => {
const client = createSvelteClient({
plugins: [testClientPlugin()],
baseURL: "http://localhost:3000",
fetchOptions: {
throw: true,
customFetchImpl: async (url, init) => {
return new Response();
},
},
});
type UseSessionAtom = ReturnType<typeof client.useSession>;
type UseSessionReturn = ReturnType<UseSessionAtom["get"]>;
type DataField = UseSessionReturn["data"];
expectTypeOf<null>().toMatchTypeOf<DataField>();
});
it("useSession().data should be nullable with `throw:true` - vanilla", () => {
const client = createVanillaClient({
plugins: [testClientPlugin()],
baseURL: "http://localhost:3000",
fetchOptions: {
throw: true,
customFetchImpl: async (url, init) => {
return new Response();
},
},
});
type UseSessionAtom = typeof client.useSession;
type UseSessionReturn = ReturnType<UseSessionAtom["get"]>;
type DataField = UseSessionReturn["data"];
expectTypeOf<null>().toMatchTypeOf<DataField>();
});
});
it("should infer `error` schema correctly", async () => {
const client = createSolidClient({
plugins: [testClientPlugin()],
@@ -51,9 +51,7 @@ type ClientSession<Option extends BetterAuthClientOptions> =
}
? Res extends BetterFetchResponse<infer S>
? S
: Res extends Record<string, any>
? Res
: never
: Res
: never;
/**
@@ -46,9 +46,7 @@ type ClientSession<Option extends BetterAuthClientOptions> =
}
? Res extends BetterFetchResponse<infer S>
? S
: Res extends Record<string, any>
? Res
: never
: Res
: never;
/**
+1 -3
View File
@@ -46,9 +46,7 @@ type ClientSession<Option extends BetterAuthClientOptions> =
}
? Res extends BetterFetchResponse<infer S>
? S
: Res extends Record<string, any>
? Res
: never
: Res
: never;
/**
+1 -3
View File
@@ -53,9 +53,7 @@ type ClientSession<Option extends BetterAuthClientOptions> =
}
? Res extends BetterFetchResponse<infer S>
? S
: Res extends Record<string, any>
? Res
: never
: Res
: never;
type VueUseSession<Option extends BetterAuthClientOptions> = {