From 4da0152c33afcede1219c0c748b9409d0d55a858 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Thu, 19 Jun 2025 14:22:05 +0200 Subject: [PATCH] Fix`useLazyFetchAllRecords` any wrong infer (#12728) # Introduction closes https://github.com/twentyhq/twenty/issues/12721 Regression seems to be introduced by https://github.com/twentyhq/twenty/pull/12653 ## Post mortem ### Previously No mapping on `namePlural` dynamic response data key ```ts const rawResult = await fetchMore({ variables: { lastCursor: lastCursor, limit, }, }); ``` ### Now Mapping is done by the tool we're consuming already ```ts const rawResult = await fetchMoreRecordsLazy(); // const fetchMoreRecordsLazy = useRecoilCallback( ({ snapshot, set }) => async () => { //... return { data: fetchMoreDataResult?.[objectMetadataItem.namePlural], totalCount: fetchMoreDataResult?.[objectMetadataItem.namePlural] ?.totalCount, records: getRecordsFromRecordConnection({ recordConnection: { edges: fetchMoreDataResult?.[objectMetadataItem.namePlural]?.edges, pageInfo: fetchMoreDataResult?.[objectMetadataItem.namePlural] ?.pageInfo, }, }) as T[], ``` ## Concerns TypeScript did not throw any errors because `RecordConnectionGql` is typed as any, we should consider adding a generic type defaulted to unknown ```ts import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge'; import { Nullable } from 'twenty-ui/utilities'; export type RecordGqlConnection = { __typename?: string; edges: RecordGqlEdge[]; pageInfo: { __typename?: string; hasNextPage?: boolean; hasPreviousPage?: boolean; startCursor?: Nullable; endCursor?: Nullable; totalCount?: number; }; totalCount?: number; [aggregateFieldName: string]: any; // Any is problematic here should be unknown }; ``` Example: ```ts export type RecordGqlConnection< T extends Record = Record, > = { __typename?: string; edges: RecordGqlEdge[]; pageInfo: { __typename?: string; hasNextPage?: boolean; hasPreviousPage?: boolean; startCursor?: Nullable; endCursor?: Nullable; totalCount?: number; }; totalCount?: number; } & T; ``` --- .../modules/object-record/hooks/useLazyFetchAllRecords.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/hooks/useLazyFetchAllRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useLazyFetchAllRecords.ts index c8dfbbe49..483c36f1e 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useLazyFetchAllRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useLazyFetchAllRecords.ts @@ -94,9 +94,9 @@ export const useLazyFetchAllRecords = ({ const rawResult = await fetchMoreRecordsLazy(); - const fetchMoreResult = rawResult?.data?.[objectMetadataItem.namePlural]; + const fetchMoreResult = rawResult?.data; - for (const edge of fetchMoreResult.edges) { + for (const edge of fetchMoreResult?.edges ?? []) { records.push(edge.node); } @@ -106,11 +106,11 @@ export const useLazyFetchAllRecords = ({ displayType: totalCount ? 'percentage' : 'number', }); - if (fetchMoreResult.pageInfo.hasNextPage === false) { + if (fetchMoreResult?.pageInfo.hasNextPage === false) { break; } - lastCursor = fetchMoreResult.pageInfo.endCursor ?? null; + lastCursor = fetchMoreResult?.pageInfo.endCursor ?? null; } setIsDownloading(false);