Skip to content

tRPC v12 isn’t on npm yet. The @trpc12/* packages on this site can’t be installed until it’s released. Use v11 today

tRPC
v11 · stable
v12 preview

Move Fast and Break Nothing.End-to-end typesafe APIs made easy.

Experience the full power of TypeScript inference to boost productivity for your full-stack application.

$ pnpm add @trpc/server @trpc/client

Experience the full power of TypeScript inference: write procedures on the server and call them from the client with their types. No schemas to generate, no code to sync. v12 is rebuilt on Effect, and you don't have to use it.

$ pnpm add @trpc12/trpc effectNot on npm yet

Supported by

const 
const trpc: TRPCClient<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>>>
trpc
=
createTRPCClient<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>>>(opts: CreateTRPCClientOptions<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>>>): TRPCClient<...>
createTRPCClient
<
type AppRouter = Router<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>> & DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>
AppRouter
>({
links: TRPCLink<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>>>[]
links
: [
httpBatchLink<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>>>(opts: HTTPBatchLinkOptions<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}>): TRPCLink<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<...>>>
httpBatchLink
({
url: string | URLurl: 'http://localhost:3000', }), ], }); const res = await
const trpc: TRPCClient<BuiltRouter<{
    ctx: object;
    meta: object;
    errorShape: DefaultErrorShape;
    transformer: false;
}, DecorateCreateRouterOptions<{
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>;
}>>>
trpc
.
greeting: {
    query: Resolver<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>;
}
greeting
.
query: (input: {
    name: string;
}, opts?: TRPCProcedureOptions) => TRPCTaggedPromise<`Hello ${string}`, DefaultErrorShape>
query
({ name: stringname: 'John' });
const res: `Hello ${string}`
src/client.ts
import { function createTrpcClient<TSource, const TLinks extends ReadonlyArray<TrpcLink<any, RouterOf<TSource>>>>(opts: TypedClientOptions<TSource, TLinks> & DuplicateSwitchCheck<TLinks> & UnmetNeedCheck<TLinks>): TrpcClient<RouterOf<TSource>, LinksContext<TLinks>, undefined, LinksTypes<TLinks>>createTrpcClient, function httpLink<TOpts extends HttpLinkOptions>(opts: TOpts): TrpcLink<HttpLinkDecl<TOpts>>httpLink, function routerType<TRouter>(): RouterType<TRouter>routerType } from '@trpc12/trpc/client';

import type { 
type AppRouter = {
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}
AppRouter
} from './server.ts';
const
const client: TrpcClient<{
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}, {}, undefined, LinksTypes<...>>
client
=
createTrpcClient<RouterType<{
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}>, readonly [...]>(opts: TypedClientOptions<...>): TrpcClient<...>
createTrpcClient
({
TypedClientOptions<RouterType<{ post: { byId: Procedure<{ type: "query"; ctx: { userId: string | null; }; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<...>; services: never; }>; create: Procedure<...>; }; }>, readonly [...]>.router: RouterType<{
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}>
router
:
routerType<{
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}>(): RouterType<...>
routerType
<
type AppRouter = {
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}
AppRouter
>(),
TypedClientOptions<RouterType<{ post: { byId: Procedure<{ type: "query"; ctx: { userId: string | null; }; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<...>; services: never; }>; create: Procedure<...>; }; }>, readonly [...]>.links: readonly [TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>]
links
: [
httpLink<{
    url: string;
}>(opts: {
    url: string;
}): TrpcLink<{
    form: JsonForm;
    provides: "response";
}, any>
httpLink
({ url: stringurl: '/trpc' })],
}); const post = await
const client: TrpcClient<{
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    };
}, {}, undefined, LinksTypes<...>>
client
.
post: ClientRouter<{
    byId: Procedure<{
        type: "query";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            id: string;
        };
        output: Post;
        errors: TrpcError<"NOT_FOUND", {
            id: string;
        }> | SchemaValidationError<ZodObject<{
            id: ZodString;
        }, $strip>>;
        services: never;
    }>;
    create: Procedure<{
        type: "mutation";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            title: string;
        };
        output: Post;
        errors: SchemaValidationError<ZodObject<{
            title: ZodString;
        }, $strip>>;
        services: never;
    }>;
}, {}, undefined, LinksTypes<...>>
post
.
byId: {
    query(input: {
        id: string;
    }, opts?: CallOptions<{}> | undefined): TrpcPromise<{
        id: string;
        title: string;
    }, CallError<{
        type: "query";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            id: string;
        };
        output: Post;
        errors: TrpcError<"NOT_FOUND", {
            id: string;
        }> | SchemaValidationError<ZodObject<{
            id: ZodString;
        }, $strip>>;
        services: never;
    }, JsonForm, never>>;
}
byId
.
function query(input: {
    id: string;
}, opts?: CallOptions<{}> | undefined): TrpcPromise<{
    id: string;
    title: string;
}, CallError<{
    type: "query";
    ctx: {
        userId: string | null;
    };
    meta: {};
    input: {
        id: string;
    };
    output: Post;
    errors: TrpcError<"NOT_FOUND", {
        id: string;
    }> | SchemaValidationError<ZodObject<{
        id: ZodString;
    }, $strip>>;
    services: never;
}, JsonForm, never>>
query
({ id: stringid: '1' });
const post: {
    id: string;
    title: string;
}

The client of the router below: the types come from the server, with nothing generated.

How it works

It's quick and easy to get started with tRPC to build a typesafe API.

  1. Define your procedures

    Define procedures
    const 
    const t: TRPCRootObject<object, object, RuntimeConfigOptions<object, object>, {
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>
    t
    = const initTRPC: TRPCBuilder<object, object>initTRPC.
    TRPCBuilder<object, object>.create<RuntimeConfigOptions<object, object>>(opts?: RuntimeConfigOptions<object, object> | undefined): TRPCRootObject<object, object, RuntimeConfigOptions<object, object>, {
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>
    create
    ();
    const
    const router: RouterBuilder<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>
    router
    =
    const t: TRPCRootObject<object, object, RuntimeConfigOptions<object, object>, {
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>
    t
    .
    TRPCRootObject<object, object, RuntimeConfigOptions<object, object>, { ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }>.router: RouterBuilder<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>
    router
    ;
    const const publicProcedure: ProcedureBuilder<object, object, object, UnsetMarker, UnsetMarker, UnsetMarker, UnsetMarker, false, DefaultErrorShape>publicProcedure =
    const t: TRPCRootObject<object, object, RuntimeConfigOptions<object, object>, {
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>
    t
    .TRPCRootObject<object, object, RuntimeConfigOptions<object, object>, { ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }>.procedure: ProcedureBuilder<object, object, object, UnsetMarker, UnsetMarker, UnsetMarker, UnsetMarker, false, DefaultErrorShape>procedure;
    const
    const appRouter: BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>
    appRouter
    =
    const router: RouterBuilder
    <{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>(_: {
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }) => BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>
    router
    ({
    greeting: QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>
    greeting
    : const publicProcedure: ProcedureBuilder<object, object, object, UnsetMarker, UnsetMarker, UnsetMarker, UnsetMarker, false, DefaultErrorShape>publicProcedure
    .
    ProcedureBuilder<object, object, object, UnsetMarker, UnsetMarker, UnsetMarker, UnsetMarker, false, DefaultErrorShape>.input<z.ZodObject<{
        name: z.ZodString;
    }, z.core.$strip>>(schema: z.ZodObject<{
        name: z.ZodString;
    }, z.core.$strip>): ProcedureBuilder<object, object, object, {
        name: string;
    }, {
        name: string;
    }, UnsetMarker, UnsetMarker, false, DefaultErrorShape>
    input
    (import zz.
    function object<{
        name: z.ZodString;
    }>(shape?: {
        name: z.ZodString;
    } | undefined, params?: string | {
        error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueUnrecognizedKeys | z.core.$ZodIssueInvalidType<unknown>>> | undefined;
        message?: string | undefined | undefined;
    } | undefined): z.ZodObject<{
        name: z.ZodString;
    }, z.core.$strip>
    object
    ({ name: z.ZodStringname: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string() }))
    .
    ProcedureBuilder<object, object, object, { name: string; }, { name: string; }, UnsetMarker, UnsetMarker, false, DefaultErrorShape>.query<`Hello ${string}`>(resolver: ProcedureResolver<object, object, object, {
        name: string;
    }, UnsetMarker, `Hello ${string}`>): QueryProcedure<{
        input: {
            name: string;
        };
        output: `Hello ${string}`;
        meta: object;
        errorShape: DefaultErrorShape;
    }>
    query
    ((
    opts: ProcedureResolverOptions<object, object, object, {
        name: string;
    }>
    opts
    ) => {
    const { input } =
    opts: ProcedureResolverOptions<object, object, object, {
        name: string;
    }>
    opts
    ;
    const input: {
        name: string;
    }
    return `Hello ${
    const input: {
        name: string;
    }
    input
    .name: stringname}` as type const = `Hello ${string}`const;
    }), }); export type
    type AppRouter = Router<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>> & DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>
    AppRouter
    = typeof
    const appRouter: BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>
    appRouter
    ;
  2. Create your HTTP server

    Adapters
    const { const listen: http.Server<any, any>listen } = 
    createHTTPServer<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{}>>>(opts: CreateHTTPHandlerOptions<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{}>>>): http.Server<any, any>
    createHTTPServer
    ({
    BaseHandlerOptions<BuiltRouter<{ ctx: object; meta: object; errorShape: DefaultErrorShape; transformer: false; }, DecorateCreateRouterOptions<{}>>, http.IncomingMessage>.router: BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{}>>
    router
    :
    const appRouter: BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{}>>
    appRouter
    ,
    }); // The API will now be listening on port 3000! const listen: http.Server<any, any>listen(3000);
  3. Connect your client and start querying!

    The vanilla client
    const 
    const trpc: TRPCClient<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>>
    trpc
    =
    createTRPCClient<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>>(opts: CreateTRPCClientOptions<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>>): TRPCClient<...>
    createTRPCClient
    <
    type AppRouter = Router<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>> & DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>
    AppRouter
    >({
    links: TRPCLink<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>>[]
    links
    : [
    httpBatchLink<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>>(opts: HTTPBatchLinkOptions<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }>): TRPCLink<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<...>>>
    httpBatchLink
    ({
    url: string | URLurl: 'http://localhost:3000', }), ], }); const res = await
    const trpc: TRPCClient<BuiltRouter<{
        ctx: object;
        meta: object;
        errorShape: DefaultErrorShape;
        transformer: false;
    }, DecorateCreateRouterOptions<{
        greeting: QueryProcedure<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            meta: object;
            errorShape: DefaultErrorShape;
        }>;
    }>>>
    trpc
    .
    greeting: {
        query: Resolver<{
            input: {
                name: string;
            };
            output: `Hello ${string}`;
            errorShape: DefaultErrorShape;
            transformer: false;
        }>;
    }
    greeting
    .
    query: (input: {
        name: string;
    }, opts?: TRPCProcedureOptions) => TRPCTaggedPromise<`Hello ${string}`, DefaultErrorShape>
    query
    ({ name: stringname: 'John' });
    const res: `Hello ${string}`

Three files' worth of code, compiled when this site builds: the types you hover are the ones your editor shows.

  1. Define procedures

    Procedures
    src/server.ts
    const 
    const t: TrpcRoot<{
        userId: string | null;
    }, {}, RootDef<{
        userId: string | null;
    }, {}>>
    t
    =
    initTrpc<{
        ctx: {
            userId: string | null;
        };
    }>(opts?: RootOptions<{}>): TrpcRoot<{
        userId: string | null;
    }, {}, RootDef<{
        userId: string | null;
    }, {}>>
    initTrpc
    <{
    ctx: {
        userId: string | null;
    }
    ctx
    : { userId: string | nulluserId: string | null } }>();
    export const
    const appRouter: {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<z.ZodObject<{
                    id: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<z.ZodObject<{
                    title: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
        };
    }
    appRouter
    = {
    post: {
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<z.ZodObject<{
                id: z.ZodString;
            }, z.core.$strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<z.ZodObject<{
                title: z.ZodString;
            }, z.core.$strip>>;
            services: never;
        }>;
    }
    post
    : {
    byId: Procedure<{
        type: "query";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            id: string;
        };
        output: Post;
        errors: TrpcError<"NOT_FOUND", {
            id: string;
        }> | SchemaValidationError<z.ZodObject<{
            id: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>
    byId
    :
    const t: TrpcRoot<{
        userId: string | null;
    }, {}, RootDef<{
        userId: string | null;
    }, {}>>
    t
    .
    TrpcRoot<{ userId: string | null; }, {}, RootDef<{ userId: string | null; }, {}>>.procedure: ProcedureBuilder<RootDef<{
        userId: string | null;
    }, {}>>
    procedure
    .
    ProcedureBuilder<RootDef<{ userId: string | null; }, {}>>.input<z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>(schema: z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>): ProcedureBuilder<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>> (+1 overload)
    input
    (import zz.
    function object<{
        id: z.ZodString;
    }>(shape?: {
        id: z.ZodString;
    } | undefined, params?: string | {
        error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
        message?: string | undefined | undefined;
    } | undefined): z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>
    object
    ({ id: z.ZodStringid: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string() }))
    .
    ProcedureBuilder<InputDef<RootDef<{ userId: string | null; }, {}>, ZodObject<{ id: ZodString; }, $strip>>>.query<Post | TrpcError<"NOT_FOUND", {
        id: string;
    }>>(resolver: (opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>>) => Post | TrpcError<"NOT_FOUND", {
        id: string;
    }>): Procedure<{
        type: "query";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            id: string;
        };
        output: Post;
        errors: TrpcError<"NOT_FOUND", {
            id: string;
        }> | SchemaValidationError<z.ZodObject<{
            id: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>
    query
    (
    (
    opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>>
    opts
    ) =>
    const posts: Map<string, Post>posts.Map<string, Post>.get(key: string): Post | undefinedget(
    opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>>
    opts
    .
    ResolverOpts<InputDef<RootDef<{ userId: string | null; }, {}>, ZodObject<{ id: ZodString; }, $strip>>>.input: {
        id: string;
    }
    input
    .id: stringid) ??
    error<"NOT_FOUND", {
        id: string;
    }>(opts: Omit<TrpcErrorOptions<"NOT_FOUND", {
        id: string;
    }>, "defined">): TrpcError<"NOT_FOUND", {
        id: string;
    }>
    error
    ({ code: "NOT_FOUND"code: 'NOT_FOUND',
    data?: {
        id: string;
    } | undefined
    data
    : { id: stringid:
    opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        id: z.ZodString;
    }, z.core.$strip>>>
    opts
    .
    ResolverOpts<InputDef<RootDef<{ userId: string | null; }, {}>, ZodObject<{ id: ZodString; }, $strip>>>.input: {
        id: string;
    }
    input
    .id: stringid } }),
    ),
    create: Procedure<{
        type: "mutation";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            title: string;
        };
        output: Post;
        errors: SchemaValidationError<z.ZodObject<{
            title: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>
    create
    :
    const t: TrpcRoot<{
        userId: string | null;
    }, {}, RootDef<{
        userId: string | null;
    }, {}>>
    t
    .
    TrpcRoot<{ userId: string | null; }, {}, RootDef<{ userId: string | null; }, {}>>.procedure: ProcedureBuilder<RootDef<{
        userId: string | null;
    }, {}>>
    procedure
    .
    ProcedureBuilder<RootDef<{ userId: string | null; }, {}>>.input<z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>>(schema: z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>): ProcedureBuilder<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>>> (+1 overload)
    input
    (import zz.
    function object<{
        title: z.ZodString;
    }>(shape?: {
        title: z.ZodString;
    } | undefined, params?: string | {
        error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
        message?: string | undefined | undefined;
    } | undefined): z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>
    object
    ({ title: z.ZodStringtitle: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string()._ZodString<$ZodStringInternals<string>>.min(minLength: number, params?: string | z.core.$ZodCheckMinLengthParams): z.ZodStringmin(1) }))
    .
    ProcedureBuilder<InputDef<RootDef<{ userId: string | null; }, {}>, ZodObject<{ title: ZodString; }, $strip>>>.mutation<Post>(resolver: (opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>>>) => Post): Procedure<{
        type: "mutation";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            title: string;
        };
        output: Post;
        errors: SchemaValidationError<z.ZodObject<{
            title: z.ZodString;
        }, z.core.$strip>>;
        services: never;
    }>
    mutation
    ((
    opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>>>
    opts
    ) => {
    const const post: Postpost: Post = { Post.id: stringid: var crypto: Cryptocrypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}`randomUUID(), Post.title: stringtitle:
    opts: ResolverOpts<InputDef<RootDef<{
        userId: string | null;
    }, {}>, z.ZodObject<{
        title: z.ZodString;
    }, z.core.$strip>>>
    opts
    .
    ResolverOpts<InputDef<RootDef<{ userId: string | null; }, {}>, ZodObject<{ title: ZodString; }, $strip>>>.input: {
        title: string;
    }
    input
    .title: stringtitle };
    const posts: Map<string, Post>posts.Map<string, Post>.set(key: string, value: Post): Map<string, Post>set(const post: Postpost.Post.id: stringid, const post: Postpost); return const post: Postpost; }), }, }; export type
    type AppRouter = {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<z.ZodObject<{
                    id: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<z.ZodObject<{
                    title: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
        };
    }
    AppRouter
    = typeof
    const appRouter: {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<z.ZodObject<{
                    id: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<z.ZodObject<{
                    title: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
        };
    }
    appRouter
    ;
  2. Serve them anywhere

    Adapters
    src/server.ts
    export const const handler: FetchHandler<undefined>handler = 
    createFetchHandler<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<z.ZodObject<{
                    id: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<z.ZodObject<{
                    title: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
        };
    }, undefined>(opts: FetchHandlerOptions<...>): FetchHandler<...>
    createFetchHandler
    ({
    BaseHandlerOptions<{ post: { byId: Procedure<{ type: "query"; ctx: { userId: string | null; }; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<ZodObject<...>>; services: never; }>; create: Procedure<...>; }; }>.router: {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<z.ZodObject<{
                    id: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<z.ZodObject<{
                    title: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
        };
    }
    router
    :
    const appRouter: {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<z.ZodObject<{
                    id: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<z.ZodObject<{
                    title: z.ZodString;
                }, z.core.$strip>>;
                services: never;
            }>;
        };
    }
    appRouter
    ,
    createContext: (opts: CreateContextOpts<undefined>) => MaybePromise<{
        userId: string | null;
    }>
    createContext
    : (opts: CreateContextOpts<undefined>opts) => ({
    userId: string | nulluserId: opts: CreateContextOpts<undefined>opts.CreateContextOpts<undefined>.request: HttpServerRequestrequest.HttpIncomingMessage<HttpServerError>.headers: Headersheaders['x-user-id'] ?? null, }), }); // Workers, Bun, Deno, Next.js route handlers: any fetch runtime. export default { fetch: (request: Request) => Promise<Response>fetch: const handler: FetchHandler<undefined>handler.FetchHandler<undefined>.fetch: (request: Request) => Promise<Response>fetch };
  3. Call them with their types

    The client
    src/client.ts
    import { function createTrpcClient<TSource, const TLinks extends ReadonlyArray<TrpcLink<any, RouterOf<TSource>>>>(opts: TypedClientOptions<TSource, TLinks> & DuplicateSwitchCheck<TLinks> & UnmetNeedCheck<TLinks>): TrpcClient<RouterOf<TSource>, LinksContext<TLinks>, undefined, LinksTypes<TLinks>>createTrpcClient, function httpLink<TOpts extends HttpLinkOptions>(opts: TOpts): TrpcLink<HttpLinkDecl<TOpts>>httpLink, function routerType<TRouter>(): RouterType<TRouter>routerType } from '@trpc12/trpc/client';
    import { function matchError<E extends AnyTrpcError, H extends ErrorHandlers<E> & { readonly [K in keyof H]: K extends HandlerKey<E> ? unknown : never; }>(err: E, handlers: H): HandlerResult<H>matchError, 
    function safe<T, E = unknown>(promise: PromiseLike<T> & {
        readonly "~error"?: E;
    }): Promise<SafeResult<T, E>>
    safe
    } from '@trpc12/trpc/client';
    import type {
    type AppRouter = {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }
    AppRouter
    } from './server.ts';
    const
    const client: TrpcClient<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }, {}, undefined, LinksTypes<...>>
    client
    =
    createTrpcClient<RouterType<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }>, readonly [...]>(opts: TypedClientOptions<...>): TrpcClient<...>
    createTrpcClient
    ({
    TypedClientOptions<RouterType<{ post: { byId: Procedure<{ type: "query"; ctx: { userId: string | null; }; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<...>; services: never; }>; create: Procedure<...>; }; }>, readonly [...]>.router: RouterType<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }>
    router
    :
    routerType<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }>(): RouterType<...>
    routerType
    <
    type AppRouter = {
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }
    AppRouter
    >(),
    TypedClientOptions<RouterType<{ post: { byId: Procedure<{ type: "query"; ctx: { userId: string | null; }; meta: {}; input: { id: string; }; output: Post; errors: TrpcError<"NOT_FOUND", { id: string; }> | SchemaValidationError<...>; services: never; }>; create: Procedure<...>; }; }>, readonly [...]>.links: readonly [TrpcLink<{
        form: JsonForm;
        provides: "response";
    }, any>]
    links
    : [
    httpLink<{
        url: string;
    }>(opts: {
        url: string;
    }): TrpcLink<{
        form: JsonForm;
        provides: "response";
    }, any>
    httpLink
    ({ url: stringurl: '/trpc' })],
    }); const post = await
    const client: TrpcClient<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }, {}, undefined, LinksTypes<...>>
    client
    .
    post: ClientRouter<{
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    }, {}, undefined, LinksTypes<...>>
    post
    .
    byId: {
        query(input: {
            id: string;
        }, opts?: CallOptions<{}> | undefined): TrpcPromise<{
            id: string;
            title: string;
        }, CallError<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }, JsonForm, never>>;
    }
    byId
    .
    function query(input: {
        id: string;
    }, opts?: CallOptions<{}> | undefined): TrpcPromise<{
        id: string;
        title: string;
    }, CallError<{
        type: "query";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            id: string;
        };
        output: Post;
        errors: TrpcError<"NOT_FOUND", {
            id: string;
        }> | SchemaValidationError<ZodObject<{
            id: ZodString;
        }, $strip>>;
        services: never;
    }, JsonForm, never>>
    query
    ({ id: stringid: '1' });
    const post: {
        id: string;
        title: string;
    }
    var console: Consoleconsole.Console.log(...data: any[]): voidlog(
    const post: {
        id: string;
        title: string;
    }
    post
    .title: stringtitle);
    const [
    const created: {
        id: string;
        title: string;
    } | undefined
    created
    ,
    const err: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 19 more ... | undefined
    err
    ] = await
    safe<{
        id: string;
        title: string;
    }, (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | ... 19 more ... | (TrpcError<...> & {
        ...;
    })>(promise: PromiseLike<...> & {
        ...;
    }): Promise<...>
    safe
    (
    const client: TrpcClient<{
        post: {
            byId: Procedure<{
                type: "query";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    id: string;
                };
                output: Post;
                errors: TrpcError<"NOT_FOUND", {
                    id: string;
                }> | SchemaValidationError<ZodObject<{
                    id: ZodString;
                }, $strip>>;
                services: never;
            }>;
            create: Procedure<{
                type: "mutation";
                ctx: {
                    userId: string | null;
                };
                meta: {};
                input: {
                    title: string;
                };
                output: Post;
                errors: SchemaValidationError<ZodObject<{
                    title: ZodString;
                }, $strip>>;
                services: never;
            }>;
        };
    }, {}, undefined, LinksTypes<...>>
    client
    .
    post: ClientRouter<{
        byId: Procedure<{
            type: "query";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                id: string;
            };
            output: Post;
            errors: TrpcError<"NOT_FOUND", {
                id: string;
            }> | SchemaValidationError<ZodObject<{
                id: ZodString;
            }, $strip>>;
            services: never;
        }>;
        create: Procedure<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }>;
    }, {}, undefined, LinksTypes<...>>
    post
    .
    create: {
        mutate(input: {
            title: string;
        }, opts?: CallOptions<{}> | undefined): TrpcPromise<{
            id: string;
            title: string;
        }, CallError<{
            type: "mutation";
            ctx: {
                userId: string | null;
            };
            meta: {};
            input: {
                title: string;
            };
            output: Post;
            errors: SchemaValidationError<ZodObject<{
                title: ZodString;
            }, $strip>>;
            services: never;
        }, JsonForm, never>>;
    }
    create
    .
    function mutate(input: {
        title: string;
    }, opts?: CallOptions<{}> | undefined): TrpcPromise<{
        id: string;
        title: string;
    }, CallError<{
        type: "mutation";
        ctx: {
            userId: string | null;
        };
        meta: {};
        input: {
            title: string;
        };
        output: Post;
        errors: SchemaValidationError<ZodObject<{
            title: ZodString;
        }, $strip>>;
        services: never;
    }, JsonForm, never>>
    mutate
    ({ title: stringtitle: '' }));
    if (
    const err: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 19 more ... | undefined
    err
    ) {
    matchError<(TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 18 more ... | (TrpcError<...> & {
        ...;
    }), {
        ...;
    }>(err: (TrpcError<...> & {
        readonly defined: false;
    }) | ... 24 more ... | (TrpcError<...> & {
        ...;
    }), handlers: {
        ...;
    }): void
    matchError
    (
    const err: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 18 more ... | (TrpcError<...> & {
        ...;
    })
    err
    , {
    type BAD_REQUEST: (e: TrpcError<"BAD_REQUEST", SchemaInputErrorData<ZodObject<{
        title: ZodString;
    }, $strip>>> & {
        readonly defined: true;
    }) => void
    BAD_REQUEST
    : (
    e: TrpcError<...> & {
        ...;
    }
    e
    ) => var console: Consoleconsole.Console.log(...data: any[]): voidlog(
    e: TrpcError<...> & {
        ...;
    }
    e
    .
    TrpcError<"BAD_REQUEST", SchemaInputErrorData<ZodObject<{ title: ZodString; }, $strip>>>.data: SchemaInputErrorData<ZodObject<{
        title: ZodString;
    }, $strip>>
    data
    .
    SchemaInputErrorData<ZodObject<{ title: ZodString; }, $strip>>.issues: readonly ({
        readonly code: "invalid_type";
        readonly expected: $ZodInvalidTypeExpected;
        readonly path: readonly [] | readonly ["title"];
        readonly message: string;
    } | {
        readonly code: "too_big";
        readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
        readonly maximum: string | number;
        readonly inclusive?: boolean | undefined;
        readonly exact?: boolean | undefined;
        readonly path: readonly [] | readonly ["title"];
        readonly message: string;
    } | {
        readonly code: "too_small";
        readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
        ... 4 more ...;
        readonly message: string;
    } | ... 8 more ... | {
        ...;
    })[]
    issues
    ),
    builtin: (e: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 17 more ... | (TrpcError<...> & {
        readonly defined: false;
    })) => void
    builtin
    : (
    e: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 17 more ... | (TrpcError<...> & {
        readonly defined: false;
    })
    e
    ) => var console: Consoleconsole.Console.log(...data: any[]): voidlog(
    e: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 17 more ... | (TrpcError<...> & {
        readonly defined: false;
    })
    e
    .TrpcError<TCode extends string = string, TData = unknown>.code: "PARSE_ERROR" | "BAD_REQUEST" | "UNSUPPORTED_PROTOCOL" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_SUPPORTED" | "TIMEOUT" | "CONFLICT" | "PRECONDITION_FAILED" | "PAYLOAD_TOO_LARGE" | "UNSUPPORTED_MEDIA_TYPE" | "UNPROCESSABLE_CONTENT" | "TOO_MANY_REQUESTS" | "CLIENT_CLOSED_REQUEST" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "GATEWAY_TIMEOUT" | "NETWORK_ERROR" | "BAD_RESPONSE" | "CLIENT_ERROR" | "STREAM_INTERRUPTED"code,
    e: (TrpcError<"PARSE_ERROR", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"BAD_REQUEST", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNSUPPORTED_PROTOCOL", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"UNAUTHORIZED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"PAYMENT_REQUIRED", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"FORBIDDEN", undefined> & {
        readonly defined: false;
    }) | (TrpcError<"NOT_FOUND", undefined> & {
        readonly defined: false;
    }) | ... 17 more ... | (TrpcError<...> & {
        readonly defined: false;
    })
    e
    .Error.message: stringmessage),
    }); } else { var console: Consoleconsole.Console.log(...data: any[]): voidlog(created.id: stringid);
    const created: {
        id: string;
        title: string;
    }
    }

FeaturesWhat's in v12

  • Automatic typesafetyMade a server side change? TypeScript will warn you of errors on your client before you even save the file!
  • Snappy DXtRPC has no build or compile steps, meaning no code generation, runtime bloat or build step.
  • Framework agnosticCompatible with all JavaScript frameworks and runtimes. It's easy to add to your existing projects.
  • AutocompletionUsing tRPC is like using an SDK for your API's server code, giving you confidence in your endpoints.
  • Light bundle sizetRPC has zero dependencies and a tiny client-side footprint making it lightweight.
  • Batteries includedWe provide adapters for React, Next.js, Express, Fastify, AWS Lambda, Solid, Svelte, and more.

One package, @trpc12/trpc, with an entry point per job and nothing to install twice.

Sponsors

tRPC is MIT licensed and built in the open, kept going by the companies and people below. Thank you!

Become a sponsor