Skip to content

TypeScript: Property 'data' does not exist on type 'Validation error' #2113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Poylar opened this issue May 26, 2025 · 6 comments
Open

TypeScript: Property 'data' does not exist on type 'Validation error' #2113

Poylar opened this issue May 26, 2025 · 6 comments
Labels
bug Something isn't working

Comments

@Poylar
Copy link

Poylar commented May 26, 2025

Hi. I tried to update to version 7.6.0, because I need a fix for safari #1918
The problem is that I already have a project in production, and when I update the version I get a lot of typescript errors.
For example, in the line:

const selectedFormat = stands.data?.data?.data?.formats?.find((stand) => stand.in_cart);
Error "Property 'data' does not exist on type 'Validation Error | GetAdvertisingDistrictFormats200'.
Property 'data' does not exist on type 'Validation error'

and so on throughout the project, since I did not take this into account during development. I understand that this can be fixed with type guard , but I just do not want to do this, since there are a lot of changes.
I found that this error starts appearing with version 7.4.0, but I did not really understand which PR is responsible for this. Can you help me figure out this problem? I can also provide the generated hooks.

this is two different gen:

export function useGetAdvertisingDistrictFormats<
  TData = Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>,
  TError = ValidationError
>(
  districtId: number,
  params: GetAdvertisingDistrictFormatsParams,
  options?: {
    query?: Partial<
      UseQueryOptions<Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>, TError, TData>
    > &
      Pick<
        UndefinedInitialDataOptions<
          Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>,
          TError,
          TData
        >,
        'initialData'
      >;
    request?: SecondParameter<typeof customFetch>;
  }
): UseQueryResult<TData, TError> & { queryKey: QueryKey };

export function useGetAdvertisingDistrictFormats<
  TData = Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>,
  TError = ValidationError
>(
  districtId: number,
  params: GetAdvertisingDistrictFormatsParams,
  options?: {
    query?: Partial<
      UseQueryOptions<Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>, TError, TData>
    > &
      Pick<
        UndefinedInitialDataOptions<
          Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>,
          TError,
          Awaited<ReturnType<typeof getAdvertisingDistrictFormats>>
        >,
        'initialData'
      >;
    request?: SecondParameter<typeof customFetch>;
  },
  queryClient?: QueryClient
): UseQueryResult<TData, TError> & { queryKey: DataTag<QueryKey, TData> };

this is my orval config:

import { defineConfig } from 'orval';

export default defineConfig({
  elevators: {
    output: {
      mode: 'tags-split',
      target: './src/api/_gen/react-query/api.ts',
      schemas: './src/api/_gen/react-query/models',
      client: 'react-query',
      clean: true,
      httpClient: 'fetch',
      baseUrl: `/api`,
      mock: false,
      prettier: true,
      override: {
        mutator: {
          path: './custom-fetch.ts',
          name: 'customFetch'
        },
        formData: {
          path: './fd.ts',
          name: 'customFormDataFn'
        }
      }
    },
    input: {
      target: `/docs/api-docs.json`
    },
    hooks: {
      afterAllFilesWrite: 'prettier --write'
    }
  },
  zod: {
    output: {
      target: './src/api/_gen/zod/zod.ts',
      client: 'zod',
      clean: true
    },
    input: {
      target: '/docs/api-docs.json'
    },
    hooks: {
      afterAllFilesWrite: 'prettier --write'
    }
  }
});

this is my custom fetch:

import { redirect } from 'next/navigation';

import { env } from '@/env.mjs';

// NOTE: Supports cases where `content-type` is other than `json`
const getBody = <T>(c: Response | Request): Promise<T> => {
  const contentType = c.headers.get('content-type');

  if (contentType && contentType.includes('application/json')) {
    return c.json();
  }

  if (contentType && contentType.includes('application/pdf')) {
    return c.blob() as Promise<T>;
  }

  return c.text() as Promise<T>;
};

// NOTE: Update just base url
const getUrl = (contextUrl: string): string => {
  const url = new URL(contextUrl);
  const pathname = url.pathname;
  const search = url.search;
  const baseUrl = env.NEXT_PUBLIC_API_URL;

  const requestUrl = new URL(`${baseUrl}${pathname}${search}`);

  return requestUrl.toString();
};

// NOTE: Add headers
const getHeaders = (headers?: HeadersInit): HeadersInit => {
  return {
    ...headers,
    'Content-Type': 'application/json',
    Accept: 'application/json'
  };
};

export const customFetch = async <T>(url: string, options: RequestInit): Promise<T> => {
  const requestUrl = getUrl(url);
  const requestHeaders = getHeaders(options.headers);

  const requestInit: RequestInit = {
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      ...requestHeaders
    },
    ...options
  };

  const request = new Request(requestUrl, requestInit);
  const response = await fetch(request);
  const data = await getBody<T>(response);

  if (response.status === 401) {
    redirect('/auth/logout');
  }

  return { status: response.status, data } as T;
};

if you need something more, just tell me.
thanks a lot

@melloware
Copy link
Collaborator

Have you tried 7.9.0 this bug might already be fixed?

@melloware melloware added the needs_reproducer Needs a reproducer to prove the issue label May 26, 2025
@Poylar
Copy link
Author

Poylar commented May 26, 2025

Have you tried 7.9.0 this bug might already be fixed?

yes, i also tried 7.9.0, same result,
i dont think this is bug...

@Poylar
Copy link
Author

Poylar commented May 26, 2025

this is just typescript error.
I just thought that upgrading to a new version would force me to change half of my codebase.

@Poylar
Copy link
Author

Poylar commented May 26, 2025

That is, I understand that either data or an error can come from the generated hook, and since the typescript does not know what exactly can come, it gives me the error that data is not in the ValidationError type, and this is true, but in version 7.2.0, I do not have this error.

for example in ver 7.2.0:

    const hook = useGeneratedHook()
   // UseQueryResult<getGeneratedHookResponse, ValidationError> & { queryKey: QueryKey;}

in 7.9,0 ver i have:

    const hook = useGeneratedHook()
   /*  UseQueryResult<getGeneratedHookResponse, ValidationError> & {
         queryKey: DataTag<QueryKey, getGeneratedHookResponse>;
   */
}

and alos in 7.2.0 i have Data | undefined
in 7.4.0> i have ValidationError | Data

@Poylar
Copy link
Author

Poylar commented May 26, 2025

This is my api docs json
{
"/advertising/districts/{district_id}/formats": {
  "get": {
    "tags": ["advertising/districts"],

    "operationId": "GetAdvertisingDistrictFormats",
    "parameters": [
      {
        "$ref": "#/components/parameters/CartHashHeader"
      },
      {
        "name": "district_id",
        "in": "path",

        "required": true,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "example": 1
        }
      },
      {
        "name": "from",
        "in": "query",

        "required": true,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2024-08-01T00:00:00.000Z"
        }
      },
      {
        "name": "to",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2024-08-31T00:00:00.000Z"
        }
      }
    ],
    "responses": {
      "200": {
        "content": {
          "application/json": {
            "schema": {
              "required": ["data"],
              "properties": {
                "data": {
                  "required": ["formats", "advertising_stands_count"],
                  "properties": {
                    "formats": {
                      "type": "array",
                      "items": {
                        "required": [
                          "id",
                          "key",
                          "name",
                          "is_rented",
                          "in_cart"
                        ],
                        "properties": {
                          "id": {
                            "type": "integer",
                            "example": 1
                          },
                          "key": {
                            "type": "integer",
                            "example": 111
                          },
                          "name": {
                            "type": "string",
                            "example": "A6"
                          },
                          "is_rented": {
                            "type": "boolean",
                            "example": false
                          },
                          "in_cart": {
                            "type": "boolean",
                            "example": false
                          }
                        },
                        "type": "object"
                      }
                    },
                    "advertising_stands_count": {
                      "type": "integer",
                      "example": 15
                    }
                  },
                  "type": "object"
                }
              },
              "type": "object"
            }
          }
        }
      },
      "422": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      }
    }
  }
}
}

@Poylar
Copy link
Author

Poylar commented May 26, 2025

@melloware i also made minimal example https://github.com/Poylar/orval-example

steps to reproduce:

  1. npm i & npm run gen
  2. npm run dev
  3. go to 'pets.tsx' file
  4. watch on 'bar' variable, no errors
  5. go to package.json and change orval version in 'gen' script to 7.9.0
  6. run npm run gen again
  7. watch on 'bar' variable, you have error Property 'data' does not exist on type 'ValidationError | GetAdvertisingDistrictFormats200'. Property 'data' does not exist on type 'ValidationError'.

@melloware melloware added bug Something isn't working and removed needs_reproducer Needs a reproducer to prove the issue labels May 26, 2025
@melloware melloware changed the title Problem with migrate from 7.2.0 to 7.4.0> TypeScript: Property 'data' does not exist on type 'Validation error' May 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants