Skip to content

fix: support exactOptionalPropertyTypes and narrow duplex type#87

Open
YevheniiKotyrlo wants to merge 1 commit intobetter-auth:mainfrom
YevheniiKotyrlo:fix/exact-optional-property-types
Open

fix: support exactOptionalPropertyTypes and narrow duplex type#87
YevheniiKotyrlo wants to merge 1 commit intobetter-auth:mainfrom
YevheniiKotyrlo:fix/exact-optional-property-types

Conversation

@YevheniiKotyrlo
Copy link
Copy Markdown

@YevheniiKotyrlo YevheniiKotyrlo commented Feb 25, 2026

Summary

  • Enable exactOptionalPropertyTypes: true in tsconfig so emitted .d.ts files don't expand optional properties with | undefined
  • Fix code patterns in create-fetch/index.ts that assign possibly-undefined values to optional properties
  • Narrow duplex type from "full" | "half" to "half" per WHATWG Fetch spec

Closes #86

Problem

The Prettify<T> mapped type causes tsup to emit | undefined on all optional properties in the inline-expanded generic default, while the constraint stays as an alias reference. With exactOptionalPropertyTypes: true, the expanded default doesn't satisfy its own constraint, producing TS2344 on betterFetch.

Changes

1. tsconfig.json — enable flag

 "strict": true,
+"exactOptionalPropertyTypes": true,

2. src/create-fetch/index.ts — conditional spreads

With exactOptionalPropertyTypes, assigning undefined to an optional property is an error. Four places need conditional spread:

 let opts = {
   ...options,
-  method: keySchema.method,
-  output: keySchema.output,
-  headers: validatedHeaders,
+  ...(keySchema.method != null ? { method: keySchema.method } : undefined),
+  ...(keySchema.output != null ? { output: keySchema.output } : undefined),
+  ...(validatedHeaders != null ? { headers: validatedHeaders } : undefined),
 };
 return {
   url,
-  options,
+  ...(options != null ? { options } : undefined),
 };

3. src/types.ts — narrow duplex

-duplex?: "full" | "half";
+duplex?: "half";

The WHATWG Fetch spec IDL enum only defines "half". Full-duplex was discussed but never standardized.

Verification

Verified on v1.1.21 (current npm release, which builds cleanly):

Gate Result
tsc --noEmit 0 errors
pnpm build (tsup) ESM, CJS, DTS all pass
DTS inspection (no | undefined in BetterFetchOption) Clean
Consumer test (exactOptionalPropertyTypes + skipLibCheck: false) 0 errors (only pre-existing Timer type leak remains)

Note on CI

CI will fail due to a pre-existing build breakage on main — undefined headers variable in utils.ts (introduced in #65, tracked in #85, fix in #81). This PR does not touch utils.ts.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 25, 2026

CLA assistant check
All committers have signed the CLA.

@YevheniiKotyrlo YevheniiKotyrlo changed the title %TITLE% fix: support exactOptionalPropertyTypes and narrow duplex type Feb 25, 2026
@YevheniiKotyrlo YevheniiKotyrlo force-pushed the fix/exact-optional-property-types branch from 82b0ab7 to dbc1a0a Compare February 25, 2026 15:28
@YevheniiKotyrlo YevheniiKotyrlo force-pushed the fix/exact-optional-property-types branch from dbc1a0a to 7a7e597 Compare February 25, 2026 15:41
Enable exactOptionalPropertyTypes in tsconfig so emitted .d.ts files
don't expand optional properties with | undefined. Fix two code
patterns in create-fetch that assign possibly-undefined values to
optional properties. Narrow duplex from "full" | "half" to "half"
per WHATWG Fetch spec.
@YevheniiKotyrlo YevheniiKotyrlo force-pushed the fix/exact-optional-property-types branch from 7a7e597 to c444890 Compare February 25, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Emitted .d.ts breaks with exactOptionalPropertyTypes: true (TS2344 on betterFetch)

2 participants