diff --git a/libs/isograph-react/src/core/cache.ts b/libs/isograph-react/src/core/cache.ts index 956646ee..51f4dcc0 100644 --- a/libs/isograph-react/src/core/cache.ts +++ b/libs/isograph-react/src/core/cache.ts @@ -516,7 +516,7 @@ function normalizeLinkedField( const dataIds: (Link | null)[] = []; for (let i = 0; i < networkResponseData.length; i++) { const networkResponseObject = networkResponseData[i]; - if (networkResponseObject === null) { + if (networkResponseObject == null) { dataIds.push(null); continue; } diff --git a/libs/isograph-react/src/core/read.ts b/libs/isograph-react/src/core/read.ts index b5152a42..60643ec7 100644 --- a/libs/isograph-react/src/core/read.ts +++ b/libs/isograph-react/src/core/read.ts @@ -342,10 +342,12 @@ function readData( }; } else { const refetchQueryIndex = field.refetchQuery; - if (refetchQueryIndex == null) { - throw new Error('refetchQuery is null in RefetchField'); - } const refetchQuery = nestedRefetchQueries[refetchQueryIndex]; + if (refetchQuery == null) { + throw new Error( + 'refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.', + ); + } const refetchQueryArtifact = refetchQuery.artifact; const allowedVariables = refetchQuery.allowedVariables; @@ -371,9 +373,15 @@ function readData( } case 'Resolver': { const usedRefetchQueries = field.usedRefetchQueries; - const resolverRefetchQueries = usedRefetchQueries.map( - (index) => nestedRefetchQueries[index], - ); + const resolverRefetchQueries = usedRefetchQueries.map((index) => { + const resolverRefetchQuery = nestedRefetchQueries[index]; + if (resolverRefetchQuery == null) { + throw new Error( + 'resolverRefetchQuery is null in Resolver. This is indicative of a bug in Isograph.', + ); + } + return resolverRefetchQuery; + }); switch (field.readerArtifact.kind) { case 'EagerReaderArtifact': { @@ -636,7 +644,12 @@ function generateChildVariableMap( const childVars: Writable = {}; for (const [name, value] of fieldArguments) { if (value.kind === 'Variable') { - childVars[name] = variables[value.name]; + const variable = variables[value.name]; + // Variable could be null if it was not provided but has a default case, + // so we allow the loop to continue rather than throwing an error. + if (variable != null) { + childVars[name] = variable; + } } else { childVars[name] = value.value; } diff --git a/libs/isograph-react/src/loadable-hooks/useConnectionSpecPagination.ts b/libs/isograph-react/src/loadable-hooks/useConnectionSpecPagination.ts index 9c672369..7d39537e 100644 --- a/libs/isograph-react/src/loadable-hooks/useConnectionSpecPagination.ts +++ b/libs/isograph-react/src/loadable-hooks/useConnectionSpecPagination.ts @@ -114,8 +114,16 @@ export function useConnectionSpecPagination< fragmentReference.readerWithRefetchQueries, ); + // invariant: readOutDataAndRecords.length === completedReferences.length + const data = readOutDataAndRecords[i]?.item; + if (data == null) { + throw new Error( + 'Parameter data is unexpectedly null. This is indicative of a bug in Isograph.', + ); + } + const firstParameter = { - data: readOutDataAndRecords[i].item, + data, parameters: fragmentReference.variables, }; @@ -165,10 +173,17 @@ export function useConnectionSpecPagination< fragmentReference.readerWithRefetchQueries, ); + const records = readOutDataAndRecords[i]; + if (records == null) { + throw new Error( + 'subscribeCompletedFragmentReferences records is unexpectedly null', + ); + } + return { fragmentReference, readerAst: readerWithRefetchQueries.readerArtifact.readerAst, - records: readOutDataAndRecords[i], + records, callback(_data) { rerender({}); }, @@ -224,10 +239,9 @@ export function useConnectionSpecPagination< const loadedReferences = state === UNASSIGNED_STATE ? [] : state; - const mostRecentItem: LoadedFragmentReference< - TReadFromStore, - Connection - > | null = loadedReferences[loadedReferences.length - 1]; + const mostRecentItem: + | LoadedFragmentReference> + | undefined = loadedReferences[loadedReferences.length - 1]; const mostRecentFragmentReference = mostRecentItem?.[0].getItemIfNotDisposed(); diff --git a/libs/isograph-react/src/loadable-hooks/useSkipLimitPagination.ts b/libs/isograph-react/src/loadable-hooks/useSkipLimitPagination.ts index 46a077fb..07d29a9a 100644 --- a/libs/isograph-react/src/loadable-hooks/useSkipLimitPagination.ts +++ b/libs/isograph-react/src/loadable-hooks/useSkipLimitPagination.ts @@ -106,8 +106,16 @@ export function useSkipLimitPagination< fragmentReference.readerWithRefetchQueries, ); + // invariant: readOutDataAndRecords.length === completedReferences.length + const data = readOutDataAndRecords[i]?.item; + if (data == null) { + throw new Error( + 'Parameter data is unexpectedly null. This is indicative of a bug in Isograph.', + ); + } + const firstParameter = { - data: readOutDataAndRecords[i].item, + data, parameters: fragmentReference.variables, }; @@ -150,10 +158,17 @@ export function useSkipLimitPagination< fragmentReference.readerWithRefetchQueries, ); + const records = readOutDataAndRecords[i]; + if (records == null) { + throw new Error( + 'subscribeCompletedFragmentReferences records is unexpectedly null', + ); + } + return { fragmentReference, readerAst: readerWithRefetchQueries.readerArtifact.readerAst, - records: readOutDataAndRecords[i], + records, callback(_data) { rerender({}); }, @@ -209,8 +224,9 @@ export function useSkipLimitPagination< const loadedReferences = state === UNASSIGNED_STATE ? [] : state; - const mostRecentItem: LoadedFragmentReference | null = - loadedReferences[loadedReferences.length - 1]; + const mostRecentItem: + | LoadedFragmentReference + | undefined = loadedReferences[loadedReferences.length - 1]; const mostRecentFragmentReference = mostRecentItem?.[0].getItemIfNotDisposed(); diff --git a/tsconfig.build.json b/tsconfig.build.json index 288b569d..3769b86f 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -15,6 +15,7 @@ "noPropertyAccessFromIndexSignature": true, "noUnusedParameters": true, "exactOptionalPropertyTypes": true, + "noUncheckedIndexedAccess": true, "paths": { "@isograph/*": ["./libs/*"] },