Skip to content

[SWR]TypeScript error in useSWRInfinite pagination when using axios client #2664

@tk1024

Description

@tk1024

Description

When using swr client with httpClient: 'axios' and swr.useInfinite: true, TypeScript compilation fails with:

TS2339: Property 'data' does not exist on type 'never'

Reproduction

Configuration

{
  output: {
    client: 'swr',
    httpClient: 'axios',
    override: {
      swr: {
        useInfinite: true,
      },
    },
  },
  input: {
    target: './petstore.yaml',
  },
}

Generated code that fails

export const getListPetsInfiniteKeyLoader = (params?: ListPetsParams) => {
  return (page: number, previousPageData?: Awaited<ReturnType<typeof listPets>>) => {
    if (previousPageData) {
      const responseData = previousPageData.data  // type: string
      if (!responseData) return null

      if (Array.isArray(responseData) && responseData.length === 0) return null

      // ERROR: After this check, TypeScript narrows `string` to `never`
      if (typeof responseData === 'object' && 'data' in responseData) {
        if (Array.isArray(responseData.data) && responseData.data.length === 0) return null
        //                          ^^^^ TS2339: Property 'data' does not exist on type 'never'
      }
      // ...
    }
  }
}

Root Cause

The pagination termination logic checks typeof responseData === 'object'. When responseData is a primitive type (e.g., string), TypeScript narrows the type to never inside the if block, causing subsequent .data property access to fail.

The fetch client works because its response type includes error objects in the union (e.g., Pet[] | Error), which survive the object check. The axios client returns AxiosResponse<T>.data which can be a primitive type.

Proposed Solution

Reorder the checks to handle primitive/non-object types before the object check:

if (previousPageData) {
  const responseData = previousPageData.data
  if (!responseData) return null

  // Direct array response - stop when empty
  if (Array.isArray(responseData) && responseData.length === 0) return null

  // Primitive types (string, number, boolean, etc.) - stop after first page
  if (typeof responseData !== 'object' || responseData === null) return null

  // Now responseData is guaranteed to be a non-null object
  if ('data' in responseData && Array.isArray(responseData.data) && responseData.data.length === 0) return null
}

Environment

  • orval version: 7.x / 8.x (both affected)
  • Node.js version: 20.x
  • TypeScript version: 5.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    swrSWR related issues

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions