typia.protobuf.*Encode โ TypeScript object โ Protocol Buffer bytes
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
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"],
});TypeScript Source
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;
}Compiled JavaScript
/* @ttsc-rewritten */
const {
_isFormatEmail: __typia_transform__isFormatEmail,
} = require("typia/lib/internal/_isFormatEmail");
const {
_isFormatUri: __typia_transform__isFormatUri,
} = require("typia/lib/internal/_isFormatUri");
const {
_isFormatUuid: __typia_transform__isFormatUuid,
} = require("typia/lib/internal/_isFormatUuid");
const {
_isTypeUint64: __typia_transform__isTypeUint64,
} = require("typia/lib/internal/_isTypeUint64");
const {
_randomFormatEmail: __typia_transform__randomFormatEmail,
} = require("typia/lib/internal/_randomFormatEmail");
const {
_randomFormatUri: __typia_transform__randomFormatUri,
} = require("typia/lib/internal/_randomFormatUri");
const {
_randomFormatUuid: __typia_transform__randomFormatUuid,
} = require("typia/lib/internal/_randomFormatUuid");
const {
_randomString: __typia_transform__randomString,
} = require("typia/lib/internal/_randomString");
const {
_randomInteger: __typia_transform__randomInteger,
} = require("typia/lib/internal/_randomInteger");
const {
_randomArray: __typia_transform__randomArray,
} = require("typia/lib/internal/_randomArray");
const {
_randomBoolean: __typia_transform__randomBoolean,
} = require("typia/lib/internal/_randomBoolean");
const {
_randomPick: __typia_transform__randomPick,
} = require("typia/lib/internal/_randomPick");
const {
_ProtobufSizer: __typia_transform__ProtobufSizer,
} = require("typia/lib/internal/_ProtobufSizer");
const {
_ProtobufWriter: __typia_transform__ProtobufWriter,
} = require("typia/lib/internal/_ProtobufWriter");
const {
_throwTypeGuardError: __typia_transform__throwTypeGuardError,
} = require("typia/lib/internal/_throwTypeGuardError");
const member = (() => {
const _ro0 = (_recursive = true, _depth = 0) => ({
id: __typia_transform__randomPick([
() =>
(_generator?.string ?? __typia_transform__randomString)({
type: "string",
"x-protobuf-sequence": 11,
}),
() =>
(_generator?.integer ?? __typia_transform__randomInteger)({
type: "integer",
minimum: 0,
"x-protobuf-sequence": 12,
}),
() =>
new Uint8Array(
5 >= _depth
? (_generator?.array ?? __typia_transform__randomArray)({
type: "array",
element: () =>
(_generator?.integer ?? __typia_transform__randomInteger)({
type: "integer",
minimum: 0,
maximum: 255,
}),
})
: [],
),
])(),
name: __typia_transform__randomPick([
() => null,
() =>
(_generator?.string ?? __typia_transform__randomString)({
type: "string",
"x-protobuf-sequence": 20,
}),
])(),
children:
5 >= _depth
? (_generator?.array ?? __typia_transform__randomArray)({
type: "array",
"x-protobuf-sequence": 30,
element: () => _ro0(true, _recursive ? 1 + _depth : _depth),
})
: [],
keywords: new Map(
5 >= _depth
? (_generator?.array ?? __typia_transform__randomArray)({
type: "array",
element: () => [
(_generator?.string ?? __typia_transform__randomString)({
type: "string",
}),
(_generator?.string ?? __typia_transform__randomString)({
type: "string",
}),
],
})
: [],
),
thumbnail: __typia_transform__randomPick([
() => (_generator?.uri ?? __typia_transform__randomFormatUri)(),
() =>
new Uint8Array(
5 >= _depth
? (_generator?.array ?? __typia_transform__randomArray)({
type: "array",
element: () =>
(_generator?.integer ?? __typia_transform__randomInteger)({
type: "integer",
minimum: 0,
maximum: 255,
}),
})
: [],
),
])(),
email: (_generator?.email ?? __typia_transform__randomFormatEmail)(),
hobbies:
5 >= _depth
? (_generator?.array ?? __typia_transform__randomArray)({
type: "array",
element: () => _ro1(true, _recursive ? 1 + _depth : _depth),
})
: [],
});
const _ro1 = (_recursive = false, _depth = 0) => ({
id: (_generator?.uuid ?? __typia_transform__randomFormatUuid)(),
name: (_generator?.string ?? __typia_transform__randomString)({
type: "string",
}),
valid: (_generator?.boolean ?? __typia_transform__randomBoolean)(),
});
let _generator;
return (generator) => {
_generator = generator;
return _ro0();
};
})()();
const byte = (() => {
const encoder = (writer, input) => {
const _peo0 = (input) => {
// property "id": ((Uint8Array & Sequence<13>) | (number & Type<"uint64"> & Sequence<12>) | (string & Sequence<11>));
if (input.id instanceof Uint8Array) {
writer.uint32(10);
writer.bytes(input.id);
} else if ("number" === typeof input.id) {
writer.uint32(16);
writer.uint64(input.id);
} else if ("string" === typeof input.id) {
writer.uint32(26);
writer.string(input.id);
} else
__typia_transform__throwTypeGuardError({
method: "encode",
expected:
'((Uint8Array & Sequence<13>) | (number & Type<"uint64"> & Sequence<12>) | (string & Sequence<11>))',
value: input.id,
});
// property "name": ((string & Sequence<20>) | null);
if (null !== input.name) {
writer.uint32(34);
writer.string(input.name);
}
// property "children": (Array<IMember> & Sequence<30>);
if (0 !== input.children.length) {
for (const elem of input.children) {
writer.uint32(42);
writer.fork();
_peo0(elem);
writer.ldelim();
}
}
// property "keywords": Map<string, string>;
for (const [key, value] of input.keywords) {
writer.uint32(50);
writer.fork();
writer.uint32(10);
writer.string(key);
writer.uint32(18);
writer.string(value);
writer.ldelim();
}
// property "thumbnail": ((string & Format<"uri"> & ContentMediaType<"image/*">) | Uint8Array);
if (input.thumbnail instanceof Uint8Array) {
writer.uint32(58);
writer.bytes(input.thumbnail);
} else if ("string" === typeof input.thumbnail) {
writer.uint32(66);
writer.string(input.thumbnail);
} else
__typia_transform__throwTypeGuardError({
method: "encode",
expected:
'((string & Format<"uri"> & ContentMediaType<"image/*">) | Uint8Array)',
value: input.thumbnail,
});
// property "email": (string & Format<"email">);
writer.uint32(74);
writer.string(input.email);
// property "hobbies": Array<IHobby>;
if (0 !== input.hobbies.length) {
for (const elem of input.hobbies) {
writer.uint32(82);
writer.fork();
_peo1(elem);
writer.ldelim();
}
}
};
const _peo1 = (input) => {
// property "id": (string & Format<"uuid">);
writer.uint32(10);
writer.string(input.id);
// property "name": string;
writer.uint32(18);
writer.string(input.name);
// property "valid": boolean;
writer.uint32(24);
writer.bool(input.valid);
};
const _io0 = (input) =>
null !== input.id &&
undefined !== input.id &&
("string" === typeof input.id ||
("number" === typeof input.id &&
__typia_transform__isTypeUint64(input.id)) ||
input.id instanceof Uint8Array) &&
(null === input.name || "string" === typeof input.name) &&
Array.isArray(input.children) &&
input.children.every(
(elem) => "object" === typeof elem && null !== elem && _io0(elem),
) &&
input.keywords instanceof Map &&
(() =>
[...input.keywords].every(
(elem) =>
Array.isArray(elem) &&
elem.length === 2 &&
"string" === typeof elem[0] &&
"string" === typeof elem[1],
))() &&
null !== input.thumbnail &&
undefined !== input.thumbnail &&
(("string" === typeof input.thumbnail &&
__typia_transform__isFormatUri(input.thumbnail)) ||
input.thumbnail instanceof Uint8Array) &&
"string" === typeof input.email &&
__typia_transform__isFormatEmail(input.email) &&
Array.isArray(input.hobbies) &&
input.hobbies.every(
(elem) => "object" === typeof elem && null !== elem && _io1(elem),
);
const _io1 = (input) =>
"string" === typeof input.id &&
__typia_transform__isFormatUuid(input.id) &&
"string" === typeof input.name &&
"boolean" === typeof input.valid;
_peo0(input);
return writer;
};
return (input) => {
const sizer = encoder(new __typia_transform__ProtobufSizer(), input);
const writer = encoder(new __typia_transform__ProtobufWriter(sizer), input);
return writer.buffer();
};
})()(member);
console.log(byte);Variants
| Function | Validates input? | On failure |
|---|---|---|
protobuf.encode<T> | No | output 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> |
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>;
}undefined
/**
* Validation result type with detailed error information.
*
* `IValidation<T>` is the return type of `typia.validate<T>()` and related
* validation functions. Unlike `typia.is<T>()` which returns a boolean, or
* `typia.assert<T>()` which throws exceptions, `typia.validate<T>()` returns
* this structured result with full error details.
*
* Check the {@link IValidation.success | success} discriminator:
*
* - `true` โ {@link IValidation.ISuccess} with validated
* {@link IValidation.ISuccess.data | data}
* - `false` โ {@link IValidation.IFailure} with
* {@link IValidation.IFailure.errors | errors} array
*
* This is the recommended validation function when you need to report
* validation errors to users or log them for debugging.
*
* @author Jeongho Nam - https://github.com/samchon
* @example
* const result = typia.validate<User>(input);
* if (result.success) {
* return result.data; // User type
* } else {
* result.errors.forEach((e) => console.log(e.path, e.expected));
* }
*
* @template T The expected type after successful validation
*/
export type IValidation<T = unknown> =
| IValidation.ISuccess<T>
| IValidation.IFailure;
export namespace IValidation {
/**
* Successful validation result.
*
* Indicates the input matches the expected type. The validated data is
* available in {@link data} with full type information.
*
* @template T The validated type
*/
export interface ISuccess<T = unknown> {
/**
* Success discriminator.
*
* Always `true` for successful validations. Use this to narrow the type
* before accessing {@link data}.
*/
success: true;
/**
* The validated data with correct type.
*
* The original input after successful validation. TypeScript will narrow
* this to type `T` when {@link success} is `true`.
*/
data: T;
}
/**
* Failed validation result with error details.
*
* Indicates the input did not match the expected type. Contains the original
* data and an array of all validation errors found.
*/
export interface IFailure {
/**
* Success discriminator.
*
* Always `false` for failed validations. Use this to narrow the type before
* accessing {@link errors}.
*/
success: false;
/**
* The original input that failed validation.
*
* Preserved as `unknown` type since it didn't match the expected type.
* Useful for debugging or logging the actual value.
*/
data: unknown;
/**
* Array of validation errors.
*
* Contains one entry for each validation failure found. Multiple errors may
* exist if the input has multiple type mismatches.
*/
errors: IError[];
}
/**
* Detailed information about a single validation error.
*
* Describes exactly what went wrong during validation, including the
* location, expected type, and actual value.
*/
export interface IError {
/**
* Property path to the error location.
*
* A dot-notation path from the root input to the failing property. Uses
* `$input` as the root. Example: `"$input.user.email"` or
* `"$input.items[0].price"`.
*/
path: string;
/**
* Expected type expression.
*
* A human-readable description of what type was expected at this location.
* Examples: `"string"`, `"number & ExclusiveMinimum<0>"`, `"(\"active\" |
* \"inactive\")"`.
*/
expected: string;
/**
* The actual value that failed validation.
*
* The value found at the error path. May be `undefined` if the property was
* missing. Useful for debugging type mismatches.
*/
value: unknown;
/**
* Human-readable error description.
*
* Optional additional context about the validation failure, such as
* constraint violations or custom error messages.
*/
description?: string;
}
}undefined
/**
* Error thrown when type assertion fails.
*
* Thrown by {@link assert}, {@link assertGuard}, and other assert-family
* functions when input doesn't match expected type `T`. Contains detailed
* information about the first assertion failure:
*
* - `method`: Which typia function threw (e.g., `"typia.assert"`)
* - `path`: Property path where error occurred (e.g., `"input.user.age"`)
* - `expected`: Expected type string (e.g., `"number & ExclusiveMinimum<19>"`)
* - `value`: Actual value that failed validation
*
* @template T Expected type (for type safety)
*/
export class TypeGuardError<T = any> extends Error {
/**
* Name of the typia method that threw this error.
*
* E.g., `"typia.assert"`, `"typia.assertEquals"`, `"typia.assertGuard"`.
*/
public readonly method: string;
/**
* Property path where assertion failed.
*
* Uses dot notation for nested properties. `undefined` if error occurred at
* root level.
*
* E.g., `"input.age"`, `"input.profile.email"`, `"input[0].name"`.
*/
public readonly path: string | undefined;
/**
* String representation of expected type.
*
* E.g., `"string"`, `"number & ExclusiveMinimum<19>"`, `"{ name: string; age:
* number }"`.
*/
public readonly expected: string;
/**
* Actual value that failed assertion.
*
* The raw value at the error path, useful for debugging.
*/
public readonly value: unknown;
/**
* Optional human-readable error description.
*
* Primarily for AI agent libraries or custom validation scenarios needing
* additional context. Standard assertions rely on `path`, `expected`, and
* `value` for error reporting.
*/
public readonly description?: string | undefined;
/**
* Phantom property for TypeScript type safety.
*
* Not used at runtimeโexists only to preserve generic type `T` in the type
* system. Always `undefined`.
*
* @internal
*/
protected readonly fake_expected_typed_value_?: T | undefined;
/**
* Creates a new TypeGuardError instance.
*
* @param props Error properties
*/
public constructor(props: TypeGuardError.IProps) {
// MESSAGE CONSTRUCTION
// Use custom message if provided, otherwise generate default format
super(
props.message ||
`Error on ${props.method}(): invalid type${
props.path ? ` on ${props.path}` : ""
}, expect to be ${props.expected}`,
);
// INHERITANCE POLYFILL
// Set up prototype for compatibility across different JavaScript environments
const proto = new.target.prototype;
if (Object.setPrototypeOf) Object.setPrototypeOf(this, proto);
else (this as any).__proto__ = proto;
// ASSIGN MEMBERS
this.name = "TypeGuardError";
this.method = props.method;
this.path = props.path;
this.expected = props.expected;
this.value = props.value;
if (props.description || props.value === undefined)
this.description =
props.description ??
[
"The value at this path is `undefined`.",
"",
`Please fill the \`${props.expected}\` typed value next time.`,
].join("\n");
}
}
export namespace TypeGuardError {
/** Properties for constructing a TypeGuardError. */
export interface IProps {
/**
* Name of the typia method that threw the error.
*
* E.g., `"typia.assert"`, `"typia.assertEquals"`.
*/
method: string;
/**
* Property path where assertion failed (optional).
*
* E.g., `"input.age"`, `"input.profile.email"`.
*/
path?: undefined | string;
/**
* String representation of expected type.
*
* E.g., `"string"`, `"number & ExclusiveMinimum<19>"`.
*/
expected: string;
/** Actual value that failed assertion. */
value: unknown;
/**
* Optional human-readable error description.
*
* For AI agent libraries or custom validation needing additional context.
*/
description?: string;
/**
* Custom error message (optional).
*
* If not provided, a default message is generated from other properties.
*/
message?: undefined | string;
}
}undefined
import { Equal } from "./internal/Equal";
import { IsTuple } from "./internal/IsTuple";
import { NativeClass } from "./internal/NativeClass";
import { ValueOf } from "./internal/ValueOf";
/**
* Converts a type to its resolved form by erasing all methods.
*
* `Resolved<T>` transforms classes to plain objects, extracts primitive values
* from boxed types (Booleanโboolean, Numberโnumber, Stringโstring), and
* recursively processes nested structures. Native classes (Date, Set, Map,
* etc.) are preserved unchanged.
*
* @author Jeongho Nam - https://github.com/samchon
* @author Kyungsu Kang - https://github.com/kakasoo
* @template T Target type to resolve
*/
export type Resolved<T> =
Equal<T, ResolvedMain<T>> extends true ? T : ResolvedMain<T>;
type ResolvedMain<T> = T extends [never]
? never // (special trick for jsonable | null) type
: ValueOf<T> extends boolean | number | bigint | string
? ValueOf<T>
: T extends Function
? never
: T extends object
? ResolvedObject<T>
: ValueOf<T>;
type ResolvedObject<T extends object> =
T extends Array<infer U>
? IsTuple<T> extends true
? ResolvedTuple<T>
: ResolvedMain<U>[]
: T extends Set<infer U>
? Set<ResolvedMain<U>>
: T extends Map<infer K, infer V>
? Map<ResolvedMain<K>, ResolvedMain<V>>
: T extends WeakSet<any> | WeakMap<any, any>
? never
: T extends NativeClass
? T
: {
[P in keyof T]: ResolvedMain<T[P]>;
};
type ResolvedTuple<T extends readonly any[]> = T extends []
? []
: T extends [infer F]
? [ResolvedMain<F>]
: T extends [infer F, ...infer Rest extends readonly any[]]
? [ResolvedMain<F>, ...ResolvedTuple<Rest>]
: T extends [(infer F)?]
? [ResolvedMain<F>?]
: T extends [(infer F)?, ...infer Rest extends readonly any[]]
? [ResolvedMain<F>?, ...ResolvedTuple<Rest>]
: [];Reusable factories
Same pattern as the other namespaces โ hoist the per-type code once:
const encodeUser = typia.protobuf.createAssertEncode<User>();TypeScript Source
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;
}Compiled JavaScript
import { _ProtobufSizer as __typia_transform__ProtobufSizer } from "typia/lib/internal/_ProtobufSizer";
import { _ProtobufWriter as __typia_transform__ProtobufWriter } from "typia/lib/internal/_ProtobufWriter";
import { _isFormatEmail as __typia_transform__isFormatEmail } from "typia/lib/internal/_isFormatEmail";
import { _isFormatUri as __typia_transform__isFormatUri } from "typia/lib/internal/_isFormatUri";
import { _isFormatUuid as __typia_transform__isFormatUuid } from "typia/lib/internal/_isFormatUuid";
import { _isTypeUint64 as __typia_transform__isTypeUint64 } from "typia/lib/internal/_isTypeUint64";
import { _throwTypeGuardError as __typia_transform__throwTypeGuardError } from "typia/lib/internal/_throwTypeGuardError";
/* @ttsc-rewritten */
export const encode = (() => {
const encoder = (writer, input) => {
const _peo0 = (input) => {
// property "id": ((Uint8Array & Sequence<13>) | (number & Type<"uint64"> & Sequence<12>) | (string & Sequence<11>));
if (input.id instanceof Uint8Array) {
writer.uint32(10);
writer.bytes(input.id);
} else if ("number" === typeof input.id) {
writer.uint32(16);
writer.uint64(input.id);
} else if ("string" === typeof input.id) {
writer.uint32(26);
writer.string(input.id);
} else
__typia_transform__throwTypeGuardError({
method: "createEncode",
expected:
'((Uint8Array & Sequence<13>) | (number & Type<"uint64"> & Sequence<12>) | (string & Sequence<11>))',
value: input.id,
});
// property "name": ((string & Sequence<20>) | null);
if (null !== input.name) {
writer.uint32(34);
writer.string(input.name);
}
// property "children": (Array<IMember> & Sequence<30>);
if (0 !== input.children.length) {
for (const elem of input.children) {
writer.uint32(42);
writer.fork();
_peo0(elem);
writer.ldelim();
}
}
// property "keywords": Map<string, string>;
for (const [key, value] of input.keywords) {
writer.uint32(50);
writer.fork();
writer.uint32(10);
writer.string(key);
writer.uint32(18);
writer.string(value);
writer.ldelim();
}
// property "thumbnail": ((string & Format<"uri"> & ContentMediaType<"image/*">) | Uint8Array);
if (input.thumbnail instanceof Uint8Array) {
writer.uint32(58);
writer.bytes(input.thumbnail);
} else if ("string" === typeof input.thumbnail) {
writer.uint32(66);
writer.string(input.thumbnail);
} else
__typia_transform__throwTypeGuardError({
method: "createEncode",
expected:
'((string & Format<"uri"> & ContentMediaType<"image/*">) | Uint8Array)',
value: input.thumbnail,
});
// property "email": (string & Format<"email">);
writer.uint32(74);
writer.string(input.email);
// property "hobbies": Array<IHobby>;
if (0 !== input.hobbies.length) {
for (const elem of input.hobbies) {
writer.uint32(82);
writer.fork();
_peo1(elem);
writer.ldelim();
}
}
};
const _peo1 = (input) => {
// property "id": (string & Format<"uuid">);
writer.uint32(10);
writer.string(input.id);
// property "name": string;
writer.uint32(18);
writer.string(input.name);
// property "valid": boolean;
writer.uint32(24);
writer.bool(input.valid);
};
const _io0 = (input) =>
null !== input.id &&
undefined !== input.id &&
("string" === typeof input.id ||
("number" === typeof input.id &&
__typia_transform__isTypeUint64(input.id)) ||
input.id instanceof Uint8Array) &&
(null === input.name || "string" === typeof input.name) &&
Array.isArray(input.children) &&
input.children.every(
(elem) => "object" === typeof elem && null !== elem && _io0(elem),
) &&
input.keywords instanceof Map &&
(() =>
[...input.keywords].every(
(elem) =>
Array.isArray(elem) &&
elem.length === 2 &&
"string" === typeof elem[0] &&
"string" === typeof elem[1],
))() &&
null !== input.thumbnail &&
undefined !== input.thumbnail &&
(("string" === typeof input.thumbnail &&
__typia_transform__isFormatUri(input.thumbnail)) ||
input.thumbnail instanceof Uint8Array) &&
"string" === typeof input.email &&
__typia_transform__isFormatEmail(input.email) &&
Array.isArray(input.hobbies) &&
input.hobbies.every(
(elem) => "object" === typeof elem && null !== elem && _io1(elem),
);
const _io1 = (input) =>
"string" === typeof input.id &&
__typia_transform__isFormatUuid(input.id) &&
"string" === typeof input.name &&
"boolean" === typeof input.valid;
_peo0(input);
return writer;
};
return (input) => {
const sizer = encoder(new __typia_transform__ProtobufSizer(), input);
const writer = encoder(new __typia_transform__ProtobufWriter(sizer), input);
return writer.buffer();
};
})();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
- Decoding the bytes back into a value โ
protobuf.decode - Sharing the schema with another language โ
protobuf.message - Numeric tags โ Special Tags