TanStackT
TanStack4mo ago
9 replies
verbal-lime

Can you please help typing this without breaking the rules of hooks?

How can I type this custom React hook that internally calls useQuery with two different query option functions, so that TypeScript infers the correct return type based on a "type" parameter?

// useDocuments.ts
import { invoiceDocumentsOptions } from "./invoice-documents/invoiceDocumentsOptions";
import { baseDocumentsOptions } from "./base-documents/baseDocumentsOptions";
import type { UseQueryResult } from "@tanstack/react-query";
import type {
  InvoiceDocumentsTable_DocumentFragment,
  DocumentsTable_DocumentFragment,
} from "@/gql/graphql";

type DocumentQueryParams =
  | {
      type: "invoiceDocuments";
      documentTypeId: string;
    }
  | {
      type: "baseDocuments";
      documentTypeId: string;
    };

type InvoiceDocumentsResult = {
  totalPages: number;
  documents: [InvoiceDocumentsTable_DocumentFragment];
};
type BaseDocumentsResult = {
  totalPages: number;
  documents: [DocumentsTable_DocumentFragment];
};

export function useDocuments({
  type,
  documentTypeId,
}: DocumentQueryParams): UseQueryResult<
  InvoiceDocumentsResult | BaseDocumentsResult,
  Error
> {
  const variables = { documentTypeId }

  if (type === "baseDocuments") {
    const queryOptions = baseDocumentsOptions(variables);

    return useQuery(queryOptions) as UseQueryResult<BaseDocumentsResult, Error>;
  }

  if (type === "invoiceDocuments") {
    const queryOptions = invoiceDocumentsOptions(variables);

    return useQuery(queryOptions) as UseQueryResult<
      InvoiceDocumentsResult,
      Error
    >;
  }

  const queryOptions = baseDocumentsOptions(variables);
  return useQuery(queryOptions) as UseQueryResult<BaseDocumentsResult, Error>;
}

When I move the useQuery call from the if statement, I get a TS error.

The above solution satisfies TS, but it feels odd and it theoretically(type is stable between renders) breaks the rules of hook. It would be very nice, if somebody can help here.

Thank you!
Was this page helpful?