Skip to Content

typia.protobuf.*Encode โ€” TypeScript object โ†’ Protocol Buffer bytes

signatures
namespace protobuf { function encode<T>(input: T): Uint8Array; // no validation function isEncode<T>(input: T): Uint8Array | null; // is + encode function assertEncode<T>(input: T): Uint8Array; // assert + encode function validateEncode<T>(input: T): IValidation<Uint8Array>; // validate + encode }

The encoder reads your type at compile time and emits a hand-rolled binary writer for that exact shape โ€” no separate .proto schema is needed. You only need protobuf.message when another service has to read the schema.

First example

hello-encode.ts
import typia from "typia"; interface User { id: string; age: number; hobbies: string[] } const bytes: Uint8Array = typia.protobuf.assertEncode<User>({ id: "1", age: 25, hobbies: ["reading"], });
examples/src/protobuf/encode.ts
import typia, { tags } from "typia"; const member: IMember = typia.random<IMember>(); const byte: Uint8Array = typia.protobuf.encode<IMember>(member); console.log(byte); interface IMember { id: | (string & tags.Sequence<11>) | (number & tags.Type<"uint64"> & tags.Sequence<12>) | (Uint8Array & tags.Sequence<13>); name: (string & tags.Sequence<20>) | null; children: Array<IMember> & tags.Sequence<30>; keywords: Map<string, string> & tags.Sequence<40>; thumbnail: | (string & tags.Format<"uri"> & tags.ContentMediaType<"image/*">) | Uint8Array; email: string & tags.Format<"email">; hobbies: Array<IHobby>; } interface IHobby { id: string & tags.Format<"uuid">; name: string; valid: boolean; }

Variants

FunctionValidates input?On failure
protobuf.encode<T>Nooutput is undefined โ€” typically the bytes will not decode
protobuf.isEncode<T>Yes (is)returns null
protobuf.assertEncode<T>Yes (assert)throws TypeGuardError
protobuf.validateEncode<T>Yes (validate)returns IValidation<Uint8Array>
Caution

protobuf.encode<T> trusts you completely.

If input doesnโ€™t actually match T, the encoder writes whatever bytes its emitted code happens to produce โ€” and the decoder on the other end will likely fail or produce garbage. Use it only when the input was constructed inside the same call frame from typed values. Otherwise, pick assertEncode or validateEncode.

undefined

export namespace protobuf { export function encode<T>(input: T): Uint8Array; export function isEncode<T>(input: T): Uint8Array | null; export function assertEncode<T>(input: T): Uint8Array; export function validateEncode<T>(input: T): IValidation<Uint8Array>; }

Reusable factories

Same pattern as the other namespaces โ€” hoist the per-type code once:

const encodeUser = typia.protobuf.createAssertEncode<User>();
examples/src/protobuf/createEncode.ts
import typia, { tags } from "typia"; export const encode = typia.protobuf.createEncode<IMember>(); interface IMember { id: | (string & tags.Sequence<11>) | (number & tags.Type<"uint64"> & tags.Sequence<12>) | (Uint8Array & tags.Sequence<13>); name: (string & tags.Sequence<20>) | null; children: Array<IMember> & tags.Sequence<30>; keywords: Map<string, string> & tags.Sequence<40>; thumbnail: | (string & tags.Format<"uri"> & tags.ContentMediaType<"image/*">) | Uint8Array; email: string & tags.Format<"email">; hobbies: Array<IHobby>; } interface IHobby { id: string & tags.Format<"uuid">; name: string; valid: boolean; }

Restrictions

The encoder follows the same type restrictions as protobuf.message: top-level type must be a single static object, no two-dimensional containers, no any/Date/Set/etc.

If you need numeric types Protocol Buffer specifies but TypeScript doesnโ€™t (e.g. uint32, int64), pick them with type tags on the property:

interface Pricing { cents: number & tags.Type<"uint32">; customerCount: bigint & tags.Type<"uint64">; }

Where to go next

Last updated on