Description
The Next.js client documentation shows request interceptors using options.headers.set() directly:
client.interceptors.request.use((options) => {
options.headers.set('Authorization', 'Bearer <my_token>')
})
This does not compile with strict: true because options.headers is typed as RequestInit['headers'] | Record<string, ...> (inherited from CoreConfig), which is a union that doesn't expose .set().
At runtime, headers is always a Headers instance — mergeHeaders() in utils.ts always returns new Headers(). But the type doesn't reflect this.
Workaround:
const headers = options.headers as unknown as Headers
headers.set('Authorization', 'Bearer token')
Suggested fix
ResolvedRequestOptions (the type passed to request interceptors) should narrow headers to Headers:
export interface ResolvedRequestOptions<
ThrowOnError extends boolean = boolean,
Url extends string = string,
> extends RequestOptions<unknown, ThrowOnError, Url> {
headers: Headers // ← narrowed, since mergeHeaders() always produces Headers
serializedBody?: string
}
The broad union on Config.headers is correct (users should be able to pass various formats), but after resolving (i.e., in interceptors), it's always Headers.
Type chain for reference
Client.interceptors = Middleware<Response, unknown, ResolvedRequestOptions>
→ ReqInterceptor<ResolvedRequestOptions> = (options: ResolvedRequestOptions) => void
→ ResolvedRequestOptions extends RequestOptions
→ RequestOptions extends Config (next/types.ts)
→ Config extends CoreConfig
→ CoreConfig.headers?: RequestInit['headers'] | Record<string, ...>
Versions
@hey-api/openapi-ts: 0.92.3
- TypeScript:
5.9.3
tsconfig.json: strict: true
Reproducible example or configuration
with a next client
import { createClient } from './generated/client/client.gen'
const client = createClient({ baseUrl: 'https://example.com' })
client.interceptors.request.use((options) => {
// TS Error: Property 'set' does not exist on type '...'
options.headers.set('Authorization', 'Bearer token')
})
OpenAPI specification (optional)
No response
System information (optional)
No response
Description
The Next.js client documentation shows request interceptors using
options.headers.set()directly:This does not compile with
strict: truebecauseoptions.headersis typed asRequestInit['headers'] | Record<string, ...>(inherited fromCoreConfig), which is a union that doesn't expose.set().At runtime,
headersis always aHeadersinstance —mergeHeaders()inutils.tsalways returnsnew Headers(). But the type doesn't reflect this.Workaround:
Suggested fix
ResolvedRequestOptions(the type passed to request interceptors) should narrowheaderstoHeaders:The broad union on
Config.headersis correct (users should be able to pass various formats), but after resolving (i.e., in interceptors), it's alwaysHeaders.Type chain for reference
Versions
@hey-api/openapi-ts:0.92.35.9.3tsconfig.json:strict: trueReproducible example or configuration
with a next client
OpenAPI specification (optional)
No response
System information (optional)
No response