#[TRPC specific] Router Types

16 messages · Page 1 of 1 (latest)

fringe gull
#

Basically I want to get the types of procedure keys and also have a guard function to check if passed in type is this particular router type or something else. Problem is that I can't export a server variable into a client variable like this.

This is what I have

// server component

export const routes = {
  users: userRouter,
  stores: storeRouter,
  skus: skuRouter,
};

export type AppRoutes = typeof routes;
// Checking if procedure has any of the keys.
type HasDeleteProcedure<T> = T extends {
  delete: unknown;
  update: unknown;
  create: unknown;
}
  ? true
  : false;

export type TRPC_ROUTE_NAMESPACES = keyof typeof routes;

export type TRPC_ROUTE_NAMESPACES_MUTABLE = {
  [K in TRPC_ROUTE_NAMESPACES]: HasDeleteProcedure<
    (typeof routes)[K]
  > extends true
    ? K
    : never;
}[TRPC_ROUTE_NAMESPACES];
export const isTRPCRouteNamespacesMutable = <T extends typeof routes>(
  value: any,
): value is keyof T => {
  return (
    typeof value === "string" &&
    Object.keys(routes).some(
      (key) =>
        key === value &&
        typeof routes[key as TRPC_ROUTE_NAMESPACES] === "object" &&
        "delete" in routes[key as TRPC_ROUTE_NAMESPACES] &&
        "update" in routes[key as TRPC_ROUTE_NAMESPACES] &&
        "create" in routes[key as TRPC_ROUTE_NAMESPACES],
    )
  );
};

I used AI to help me with the types lol.

stable flicker
#

Some of the things you say and some of the code don't make sense

#

Your trpcServer has some "routes", some of these will be sub routers with delete, update, and create?

#

And you want to check whether a trpc route matches this shape?

#

You have HadDeleteProcedure, but then it references delete, update and create. Should that only reference delete, or should it be named differently?

#

For shared code you can create a simple shared package and import it both on the client and the server

#

Or if you only use it on the client, create it on the client, while importing only the types

#

Types are removed at compile time, so you can use types between server and client without a problem

fringe gull
fringe gull
stable flicker
#

right

#

Well yeah, you can't inspect the routes on the server, from the client

#

So I suppose you just need to use the type info you have to make decisions on the client

#

You can write a type that determines whether a route has those subroutes, without involving any runtime code

#

Well you have it already

#

You can do something like

type ValidRoute<T> = T extends {
  delete: unknown;
  update: unknown;
  create: unknown;
}
  ? T
  : 'invalid route';

function useRoute<R>(route: ValidRoute<R>) {
  ///
}