Tipos de Contenido
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
tRPC admite múltiples tipos de contenido como entradas de procedimientos: datos serializables en JSON, FormData, File, Blob y otros tipos binarios.
JSON (Predeterminado)
Por defecto, tRPC envía y recibe datos serializables en JSON. No se necesita configuración adicional: cualquier entrada que pueda serializarse a JSON funciona inmediatamente con todos los links (httpLink, httpBatchLink, httpBatchStreamLink).
tsimport {z } from 'zod';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({hello :publicProcedure .input (z .object ({name :z .string () })).query ((opts ) => {return {greeting : `Hello ${opts .input .name }` };}),});
tsimport {z } from 'zod';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({hello :publicProcedure .input (z .object ({name :z .string () })).query ((opts ) => {return {greeting : `Hello ${opts .input .name }` };}),});
Tipos de Contenido no JSON
Además de JSON, tRPC puede usar FormData, File y otros tipos binarios como entradas de procedimientos.
Configuración del Cliente
Aunque tRPC admite nativamente varios tipos no serializables en JSON, tu cliente podría necesitar cierta configuración de links para soportarlos según tu configuración.
httpLink admite tipos de contenido no JSON inmediatamente. Si solo usas este link, tu configuración actual debería funcionar sin cambios.
tsimport {createTRPCClient ,httpLink } from '@trpc/client';import type {AppRouter } from './server';createTRPCClient <AppRouter >({links : [httpLink ({url : 'http://localhost:2022',}),],});
tsimport {createTRPCClient ,httpLink } from '@trpc/client';import type {AppRouter } from './server';createTRPCClient <AppRouter >({links : [httpLink ({url : 'http://localhost:2022',}),],});
Sin embargo, no todos los links admiten estos tipos de contenido. Si usas httpBatchLink o httpBatchStreamLink, necesitarás incluir un splitLink y enrutar las solicitudes según el tipo de contenido.
tsimport {createTRPCClient ,httpBatchLink ,httpLink ,isNonJsonSerializable ,splitLink ,} from '@trpc/client';import type {AppRouter } from './server';consturl = 'http://localhost:2022';createTRPCClient <AppRouter >({links : [splitLink ({condition : (op ) =>isNonJsonSerializable (op .input ),true :httpLink ({url ,}),false :httpBatchLink ({url ,}),}),],});
tsimport {createTRPCClient ,httpBatchLink ,httpLink ,isNonJsonSerializable ,splitLink ,} from '@trpc/client';import type {AppRouter } from './server';consturl = 'http://localhost:2022';createTRPCClient <AppRouter >({links : [splitLink ({condition : (op ) =>isNonJsonSerializable (op .input ),true :httpLink ({url ,}),false :httpBatchLink ({url ,}),}),],});
Si usas transformer en tu servidor tRPC, TypeScript requiere que tu link del cliente tRPC también defina transformer.
Usa este ejemplo como base:
tsimport {createTRPCClient ,httpBatchLink ,httpLink ,isNonJsonSerializable ,splitLink ,} from '@trpc/client';importsuperjson from 'superjson';import type {AppRouter } from './server';consturl = 'http://localhost:2022';createTRPCClient <AppRouter >({links : [splitLink ({condition : (op ) =>isNonJsonSerializable (op .input ),true :httpLink ({url ,transformer : {// request - convert data before sending to the tRPC serverserialize : (data ) =>data ,// response - convert the tRPC response before using it in clientdeserialize : (data ) =>superjson .deserialize (data ), // or your other transformer},}),false :httpBatchLink ({url ,transformer :superjson , // or your other transformer}),}),],});
tsimport {createTRPCClient ,httpBatchLink ,httpLink ,isNonJsonSerializable ,splitLink ,} from '@trpc/client';importsuperjson from 'superjson';import type {AppRouter } from './server';consturl = 'http://localhost:2022';createTRPCClient <AppRouter >({links : [splitLink ({condition : (op ) =>isNonJsonSerializable (op .input ),true :httpLink ({url ,transformer : {// request - convert data before sending to the tRPC serverserialize : (data ) =>data ,// response - convert the tRPC response before using it in clientdeserialize : (data ) =>superjson .deserialize (data ), // or your other transformer},}),false :httpBatchLink ({url ,transformer :superjson , // or your other transformer}),}),],});
Configuración del Servidor
Cuando tRPC maneja una solicitud, se encarga de analizar el cuerpo según el encabezado Content-Type.
Si encuentras errores como Failed to parse body as XXX, verifica que tu servidor (ej. Express, Next.js) no esté analizando el cuerpo antes de que tRPC lo maneje.
ts// Example in expressimportexpress from 'express';import * astrpcExpress from '@trpc/server/adapters/express';import {appRouter } from './router';// incorrectconstapp1 =express ();app1 .use (express .json ()); // this tries to parse body before tRPC.app1 .post ('/express/hello', (req ,res ) => {res .end (); }); // normal express route handlerapp1 .use ('/trpc',trpcExpress .createExpressMiddleware ({router :appRouter })); // tRPC fails to parse body// correctconstapp2 =express ();app2 .use ('/express',express .json ()); // do it only in "/express/*" pathapp2 .post ('/express/hello', (req ,res ) => {res .end (); });app2 .use ('/trpc',trpcExpress .createExpressMiddleware ({router :appRouter })); // tRPC can parse body
ts// Example in expressimportexpress from 'express';import * astrpcExpress from '@trpc/server/adapters/express';import {appRouter } from './router';// incorrectconstapp1 =express ();app1 .use (express .json ()); // this tries to parse body before tRPC.app1 .post ('/express/hello', (req ,res ) => {res .end (); }); // normal express route handlerapp1 .use ('/trpc',trpcExpress .createExpressMiddleware ({router :appRouter })); // tRPC fails to parse body// correctconstapp2 =express ();app2 .use ('/express',express .json ()); // do it only in "/express/*" pathapp2 .post ('/express/hello', (req ,res ) => {res .end (); });app2 .use ('/trpc',trpcExpress .createExpressMiddleware ({router :appRouter })); // tRPC can parse body
Entrada FormData
FormData tiene soporte nativo. Para usos más avanzados, puedes combinarlo con bibliotecas como zod-form-data para validar entradas de forma tipada.
tsimport {z } from 'zod';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({hello :publicProcedure .input (z .instanceof (FormData )).mutation ((opts ) => {constdata =opts .input ;return {greeting : `Hello ${data .get ('name')}`,};}),});
tsimport {z } from 'zod';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({hello :publicProcedure .input (z .instanceof (FormData )).mutation ((opts ) => {constdata =opts .input ;return {greeting : `Hello ${data .get ('name')}`,};}),});
Para un ejemplo de código más avanzado, consulta nuestro proyecto de ejemplo aquí
Entradas File y Otros Tipos Binarios
tRPC convierte muchos tipos de contenido octet a un ReadableStream que puede consumirse en un procedimiento. Actualmente estos incluyen Blob, Uint8Array y File.
tsimport {octetInputParser } from '@trpc/server/http';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({upload :publicProcedure .input (octetInputParser ).mutation ((opts ) => {constdata =opts .input ;return {valid : true,};}),});
tsimport {octetInputParser } from '@trpc/server/http';export constt =initTRPC .create ();constpublicProcedure =t .procedure ;export constappRouter =t .router ({upload :publicProcedure .input (octetInputParser ).mutation ((opts ) => {constdata =opts .input ;return {valid : true,};}),});