1

I'm trying to make a wrapper around every call to trpc.useQuery. It should look something like this:

function wrapper(pathAndInput) {
  const result = trpc.useQuery(pathAndInput)
  /* some code that also uses `pathAndInput` */
  return result
}

However I can't make work the fact that the pathAndInput can have a variadic second element. I.e. in trpc.useQuery(["key", params], options) the params part is optional.

The type I have so far is this:

function useIndexedTRcpQuery<TRouteKey extends TQuery>(
    pathAndInput: inferQueryInput<TRouteKey> extends (undefined | void | null)
        ? [TRouteKey]
        : [TRouteKey, inferQueryInput<TRouteKey>]
): UseQueryResult<inferQueryOutput<TRouteKey>>

However I get the following typescript error:

trpc.useQuery(pathAndInput)
              ^^^^^^^^^^^^
Source has 1 element(s) but target requires 2

I have also tried the following:

function useIndexedTRcpQuery<TRouteKey extends TQuery>(
    pathAndInput: [
        key: TRouteKey,
        args?: inferQueryInput<TRouteKey>,
    ],
): UseQueryResult<inferQueryOutput<TRouteKey>>

Which gives the following error :

trpc.useQuery(pathAndInput)
              ^^^^^^^^^^^^
Source provides no match for variadic element at position 1 in target

What is the correct way to type the first argument of trpc.useQuery as a generic?


For reference, here are what the "utils types" are in the above code (pretty standard trpc stuff):

import type { UseQueryResult } from "react-query";
import type { inferProcedureOutput, inferProcedureInput } from "@trpc/server";

type TQuery = keyof AppRouter["_def"]["queries"];

type inferQueryInput<
  TRouteKey extends TQuery,
> = inferProcedureInput<AppRouter["_def"]["queries"][TRouteKey]>;

type inferQueryOutput<
  TRouteKey extends TQuery,
> = inferProcedureOutput<AppRouter["_def"]["queries"][TRouteKey]>;
Sheraff
  • 5,730
  • 3
  • 28
  • 53

1 Answers1

1

First you may define a type in the trpc.ts file. (or wherever you defined the other "pretty standard trpc stuff".

export type TUseQuery = [
  TQuery, // we use the already existing TQuery type which holds all possible querys
  Record<string, any> // We use a Record to type the Object consisting of keys in the form of strings and any possible input.
];

After that we can use the Type to type a query Parameter.

import { trpc, TUseQuery } from "../utils/trpc"; // path to your trpc file

let query: TUseQuery= [
    "example.hello", // trpcQuery
    { text: "from tRPC" }, // trpcQuery Input Object
] 

function laodData(query: TUseQuery) : UseQueryResult {
  return trpc.useQuery(query) 
}

console.log(laodData(query));

et voila.

PS: testet in the t3-demo-app.