Hoppa till huvudinnehållet
Version: 11.x

Innehållstyper

Inofficiell Beta-översättning

Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →

tRPC stöder flera innehållstyper som procedurindata: JSON-serialiserbar data, FormData, File, Blob och andra binära typer.

JSON (Standard)

Som standard skickar och tar emot tRPC JSON-serialiserbar data. Ingen extra konfiguration behövs – all indata som kan serialiseras till JSON fungerar direkt med alla länkar (httpLink, httpBatchLink, httpBatchStreamLink).

ts
import { z } from 'zod';
 
export const t = initTRPC.create();
const publicProcedure = t.procedure;
 
export const appRouter = t.router({
hello: publicProcedure.input(z.object({ name: z.string() })).query((opts) => {
return { greeting: `Hello ${opts.input.name}` };
}),
});
ts
import { z } from 'zod';
 
export const t = initTRPC.create();
const publicProcedure = t.procedure;
 
export const appRouter = t.router({
hello: publicProcedure.input(z.object({ name: z.string() })).query((opts) => {
return { greeting: `Hello ${opts.input.name}` };
}),
});

Icke-JSON-innehållstyper

Förutom JSON kan tRPC använda FormData, File och andra binära typer som procedurindata.

Klientinställningar

information

Även om tRPC internt stöder flera icke-JSON-serialiserbara typer kan din klient behöva en liten länkkonfiguration för att stödja dem beroende på din inställning.

httpLink stöder icke-JSON-innehållstyper direkt – om du bara använder den här länken ska din befintliga inställning fungera omedelbart.

ts
import { createTRPCClient, httpLink } from '@trpc/client';
import type { AppRouter } from './server';
 
createTRPCClient<AppRouter>({
links: [
httpLink({
url: 'http://localhost:2022',
}),
],
});
ts
import { createTRPCClient, httpLink } from '@trpc/client';
import type { AppRouter } from './server';
 
createTRPCClient<AppRouter>({
links: [
httpLink({
url: 'http://localhost:2022',
}),
],
});

Däremot stöder inte alla länkar dessa innehållstyper. Om du använder httpBatchLink eller httpBatchStreamLink måste du inkludera en splitLink och dirigera förfrågningar baserat på innehållstypen.

ts
import {
createTRPCClient,
httpBatchLink,
httpLink,
isNonJsonSerializable,
splitLink,
} from '@trpc/client';
import type { AppRouter } from './server';
 
const url = 'http://localhost:2022';
 
createTRPCClient<AppRouter>({
links: [
splitLink({
condition: (op) => isNonJsonSerializable(op.input),
true: httpLink({
url,
}),
false: httpBatchLink({
url,
}),
}),
],
});
ts
import {
createTRPCClient,
httpBatchLink,
httpLink,
isNonJsonSerializable,
splitLink,
} from '@trpc/client';
import type { AppRouter } from './server';
 
const url = 'http://localhost:2022';
 
createTRPCClient<AppRouter>({
links: [
splitLink({
condition: (op) => isNonJsonSerializable(op.input),
true: httpLink({
url,
}),
false: httpBatchLink({
url,
}),
}),
],
});

Om du använder transformer i din tRPC-server kräver TypeScript att din tRPC-klientlänk också definierar transformer. Använd det här exemplet som grund:

ts
import {
createTRPCClient,
httpBatchLink,
httpLink,
isNonJsonSerializable,
splitLink,
} from '@trpc/client';
import superjson from 'superjson';
import type { AppRouter } from './server';
 
const url = 'http://localhost:2022';
 
createTRPCClient<AppRouter>({
links: [
splitLink({
condition: (op) => isNonJsonSerializable(op.input),
true: httpLink({
url,
transformer: {
// request - convert data before sending to the tRPC server
serialize: (data) => data,
// response - convert the tRPC response before using it in client
deserialize: (data) => superjson.deserialize(data), // or your other transformer
},
}),
false: httpBatchLink({
url,
transformer: superjson, // or your other transformer
}),
}),
],
});
ts
import {
createTRPCClient,
httpBatchLink,
httpLink,
isNonJsonSerializable,
splitLink,
} from '@trpc/client';
import superjson from 'superjson';
import type { AppRouter } from './server';
 
const url = 'http://localhost:2022';
 
createTRPCClient<AppRouter>({
links: [
splitLink({
condition: (op) => isNonJsonSerializable(op.input),
true: httpLink({
url,
transformer: {
// request - convert data before sending to the tRPC server
serialize: (data) => data,
// response - convert the tRPC response before using it in client
deserialize: (data) => superjson.deserialize(data), // or your other transformer
},
}),
false: httpBatchLink({
url,
transformer: superjson, // or your other transformer
}),
}),
],
});

Serverinställningar

information

När en förfrågan hanteras av tRPC tar den hand om att tolka förfrågans kropp baserat på Content-Type-headern.
Om du stöter på fel som Failed to parse body as XXX, se till att din server (t.ex. Express, Next.js) inte tolkar förfrågans kropp innan tRPC hanterar den.

ts
// Example in express
import express from 'express';
import * as trpcExpress from '@trpc/server/adapters/express';
import { appRouter } from './router';
 
// incorrect
const app1 = express();
app1.use(express.json()); // this tries to parse body before tRPC.
app1.post('/express/hello', (req, res) => { res.end(); }); // normal express route handler
app1.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter })); // tRPC fails to parse body
 
// correct
const app2 = express();
app2.use('/express', express.json()); // do it only in "/express/*" path
app2.post('/express/hello', (req, res) => { res.end(); });
app2.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter })); // tRPC can parse body
ts
// Example in express
import express from 'express';
import * as trpcExpress from '@trpc/server/adapters/express';
import { appRouter } from './router';
 
// incorrect
const app1 = express();
app1.use(express.json()); // this tries to parse body before tRPC.
app1.post('/express/hello', (req, res) => { res.end(); }); // normal express route handler
app1.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter })); // tRPC fails to parse body
 
// correct
const app2 = express();
app2.use('/express', express.json()); // do it only in "/express/*" path
app2.post('/express/hello', (req, res) => { res.end(); });
app2.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter })); // tRPC can parse body

FormData-indata

FormData stöds internt, och för mer avancerad användning kan du kombinera detta med bibliotek som zod-form-data för att validera indata på ett typsäkert sätt.

ts
import { z } from 'zod';
 
export const t = initTRPC.create();
const publicProcedure = t.procedure;
 
export const appRouter = t.router({
hello: publicProcedure.input(z.instanceof(FormData)).mutation((opts) => {
const data = opts.input;
const data: FormData
return {
greeting: `Hello ${data.get('name')}`,
};
}),
});
ts
import { z } from 'zod';
 
export const t = initTRPC.create();
const publicProcedure = t.procedure;
 
export const appRouter = t.router({
hello: publicProcedure.input(z.instanceof(FormData)).mutation((opts) => {
const data = opts.input;
const data: FormData
return {
greeting: `Hello ${data.get('name')}`,
};
}),
});

För ett mer avancerat kodexempel kan du titta på vårt exempelprojekt här

File och andra binära typer som indata

tRPC konverterar många oktett-innehållstyper till en ReadableStream som kan användas i en procedur. För närvarande gäller detta Blob, Uint8Array och File.

ts
import { octetInputParser } from '@trpc/server/http';
 
export const t = initTRPC.create();
const publicProcedure = t.procedure;
 
export const appRouter = t.router({
upload: publicProcedure.input(octetInputParser).mutation((opts) => {
const data = opts.input;
const data: ReadableStream<any>
return {
valid: true,
};
}),
});
ts
import { octetInputParser } from '@trpc/server/http';
 
export const t = initTRPC.create();
const publicProcedure = t.procedure;
 
export const appRouter = t.router({
upload: publicProcedure.input(octetInputParser).mutation((opts) => {
const data = opts.input;
const data: ReadableStream<any>
return {
valid: true,
};
}),
});