[GH-ISSUE #1578] twoFactor() is incompatible with exactOptionalPropertyTypes #17457

Closed
opened 2026-04-15 15:35:37 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @alexwork1611 on GitHub (Feb 26, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/1578

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Create a Better Auth basic config with twoFactor()
  2. Use exactOptionalPropertyTypes in TS Config

My tsconfig.json (based on https://github.com/tsconfig/bases/blob/main/bases/strictest.json):

{
	"extends": [
		"@tsconfig/strictest/tsconfig.json"
	],
	"compilerOptions": {
		"baseUrl": ".",
		"module": "ESNext",
		"target": "ES2022",
		"moduleResolution": "Bundler",
		"jsx": "react-jsx",
		"resolveJsonModule": true,
		"paths": {
			"@/*": [
				"./app/*"
			],
			"~prisma/*": [
				"./prisma/*"
			]
		},
		"outDir": "dist"
	},
}

Current vs. Expected behavior

When I am using exactOptionalPropertyTypes, I am getting an error:

Type '{ id: "two-factor"; endpoints: { enableTwoFactor: { <C extends [better_call.Context<"/two-factor/enable", { method: "POST"; body: z.ZodObject<{ password: z.ZodString; }, "strip", z.ZodTypeAny, { password: string; }, { password: string; }>; use: better_call.Endpoint<better_call.Handler<string, better_call.EndpointOpt...' is not assignable to type 'BetterAuthPlugin' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
  The types of 'hooks.after' are incompatible between these types.
    Type '{ matcher(context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>): boolean; handler: Endpoint<...>; }[]' is not assignable to type '{ matcher: (context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>) => boolean; handler: HookAfterHandler; }[]'.
      Type '{ matcher(context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>): boolean; handler: Endpoint<...>; }' is not assignable to type '{ matcher: (context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>) => boolean; handler: HookAfterHandler; }'.
        Types of property 'handler' are incompatible.
          Type 'Endpoint<Handler<string, EndpointOptions, { response: { body: any; status: number; statusText: string; headers: Record<string, string> | undefined; }; body: { twoFactorRedirect: boolean; }; _flag: "json"; } | undefined>, EndpointOptions>' is not assignable to type 'HookAfterHandler'.
            Types of parameters 'ctx' and 'context' are incompatible.
              Type 'HookEndpointContext<{}>' is not assignable to type '{ body: { [x: string]: any; }; params?: Record<string, string>; method?: "GET"; headers: Headers; request: Request; query?: undefined; _flag?: "default" | "json" | "router"; ... 9 more ...; responseHeader: Headers; } | ... 110 more ... | { ...; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
                Type 'HookEndpointContext<{}>' is not assignable to type '{ body: { [x: string]: any; }; params?: Record<string, string>; method: Method; headers?: Headers; request?: Request; query: any; _flag?: "default" | "json" | "router"; ... 10 more ...; responseHeader: Headers; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
                  Types of property 'params' are incompatible.
                    Type 'Record<string, string> | undefined' is not assignable to type 'Record<string, string>'.
                      Type 'undefined' is not assignable to type 'Record<string, string>'.ts(2375)

Image

What version of Better Auth are you using?

1.1.21

Provide environment information

TypeScript version: 5.7.3

Which area(s) are affected? (Select all that apply)

Types

Auth config (if applicable)

export const auth = betterAuth({
	plugins: [passkey(), twoFactor()],
})

Additional context

No response

Originally created by @alexwork1611 on GitHub (Feb 26, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/1578 ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Create a Better Auth basic config with `twoFactor()` 2. Use `exactOptionalPropertyTypes` in TS Config My `tsconfig.json` (based on https://github.com/tsconfig/bases/blob/main/bases/strictest.json): ``` { "extends": [ "@tsconfig/strictest/tsconfig.json" ], "compilerOptions": { "baseUrl": ".", "module": "ESNext", "target": "ES2022", "moduleResolution": "Bundler", "jsx": "react-jsx", "resolveJsonModule": true, "paths": { "@/*": [ "./app/*" ], "~prisma/*": [ "./prisma/*" ] }, "outDir": "dist" }, } ``` ### Current vs. Expected behavior When I am using `exactOptionalPropertyTypes`, I am getting an error: ``` Type '{ id: "two-factor"; endpoints: { enableTwoFactor: { <C extends [better_call.Context<"/two-factor/enable", { method: "POST"; body: z.ZodObject<{ password: z.ZodString; }, "strip", z.ZodTypeAny, { password: string; }, { password: string; }>; use: better_call.Endpoint<better_call.Handler<string, better_call.EndpointOpt...' is not assignable to type 'BetterAuthPlugin' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties. The types of 'hooks.after' are incompatible between these types. Type '{ matcher(context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>): boolean; handler: Endpoint<...>; }[]' is not assignable to type '{ matcher: (context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>) => boolean; handler: HookAfterHandler; }[]'. Type '{ matcher(context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>): boolean; handler: Endpoint<...>; }' is not assignable to type '{ matcher: (context: HookEndpointContext<{ returned: Record<string, any> | Response | APIError; endpoint: Endpoint; }>) => boolean; handler: HookAfterHandler; }'. Types of property 'handler' are incompatible. Type 'Endpoint<Handler<string, EndpointOptions, { response: { body: any; status: number; statusText: string; headers: Record<string, string> | undefined; }; body: { twoFactorRedirect: boolean; }; _flag: "json"; } | undefined>, EndpointOptions>' is not assignable to type 'HookAfterHandler'. Types of parameters 'ctx' and 'context' are incompatible. Type 'HookEndpointContext<{}>' is not assignable to type '{ body: { [x: string]: any; }; params?: Record<string, string>; method?: "GET"; headers: Headers; request: Request; query?: undefined; _flag?: "default" | "json" | "router"; ... 9 more ...; responseHeader: Headers; } | ... 110 more ... | { ...; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties. Type 'HookEndpointContext<{}>' is not assignable to type '{ body: { [x: string]: any; }; params?: Record<string, string>; method: Method; headers?: Headers; request?: Request; query: any; _flag?: "default" | "json" | "router"; ... 10 more ...; responseHeader: Headers; }' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties. Types of property 'params' are incompatible. Type 'Record<string, string> | undefined' is not assignable to type 'Record<string, string>'. Type 'undefined' is not assignable to type 'Record<string, string>'.ts(2375) ``` ![Image](https://github.com/user-attachments/assets/fb659880-539d-40e8-acf2-c7cbb3fc3281) ### What version of Better Auth are you using? 1.1.21 ### Provide environment information ```bash TypeScript version: 5.7.3 ``` ### Which area(s) are affected? (Select all that apply) Types ### Auth config (if applicable) ```typescript export const auth = betterAuth({ plugins: [passkey(), twoFactor()], }) ``` ### Additional context _No response_
GiteaMirror added the lockedbug labels 2026-04-15 15:35:37 -05:00
Author
Owner

@Nick-Mazuk commented on GitHub (Apr 21, 2025):

Running into this as well. Here's a minimal reproduction:

https://github.com/Nick-Mazuk/better-auth-2fa-repro

<!-- gh-comment-id:2819701460 --> @Nick-Mazuk commented on GitHub (Apr 21, 2025): Running into this as well. Here's a minimal reproduction: https://github.com/Nick-Mazuk/better-auth-2fa-repro
Author
Owner

@csulit commented on GitHub (May 12, 2025):

try this twoFactor() as unknown as BetterAuthPlugin as temporary solution

<!-- gh-comment-id:2872721637 --> @csulit commented on GitHub (May 12, 2025): try this` twoFactor() as unknown as BetterAuthPlugin` as temporary solution
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#17457