Skip to main content
Version: 1.0

Type Registration

Every struct and enum you serialize must be registered with the Fory instance before use. Registration tells Fory how to identify the type in a message and how to encode and decode it.

Registering Structs​

You can identify a struct with a numeric ID or with a name. Pick one strategy and use it consistently across all languages that share the same messages.

Register by numeric ID​

Smaller wire representation. Good when a small team can coordinate IDs.

const userType = Type.struct(
{ typeId: 1001 },
{
id: Type.int64(),
name: Type.string(),
},
);

const fory = new Fory();
const { serialize, deserialize } = fory.register(userType);

The same number must be used in every runtime that reads or writes this type.

Register by name​

Easier to coordinate across teams. Slightly larger metadata in the message.

const userType = Type.struct(
{ typeName: "example.user" },
{
id: Type.int64(),
name: Type.string(),
},
);

const fory = new Fory();
const { serialize, deserialize } = fory.register(userType);

You can also split namespace and type name explicitly:

const userType = Type.struct(
{ namespace: "example", typeName: "user" },
{
id: Type.int64(),
name: Type.string(),
},
);

Do not mix strategies for the same type across runtimes. If one side uses a numeric ID and the other uses a name, deserialization will fail.

Registering with Decorators​

@Type.struct({ typeId: 1001 })
class User {
@Type.int64()
id!: bigint;

@Type.string()
name!: string;
}

const fory = new Fory();
const { serialize, deserialize } = fory.register(User);

Decorator-based registration is convenient when you want your TypeScript class declaration and schema to live together.

Registering Enums​

Fory JavaScript supports both plain JavaScript enum-like objects and TypeScript enums.

JavaScript object enum​

const Color = {
Red: 1,
Green: 2,
Blue: 3,
};

const fory = new Fory();
const colorSerde = fory.register(Type.enum("example.color", Color));

TypeScript enum​

enum Status {
Pending = "pending",
Active = "active",
}

const fory = new Fory();
fory.register(Type.enum("example.status", Status));

Registration Scope​

Registration is per Fory instance. If you create two instances, you need to register schemas in both.

What register Returns​

fory.register(schema) returns a bound serializer pair:

const { serialize, deserialize } = fory.register(orderType);

// serialize returns Uint8Array bytes
const bytes = serialize({ id: 1n, total: 99.99 });

// deserialize returns the decoded value
const order = deserialize(bytes);

Store and reuse this pair — it is the fast path.

Field Metadata​

Field nullability, reference tracking, dynamic field behavior, numeric widths, and per-struct schema-evolution metadata are covered in Schema Metadata.

Choosing IDs vs Names​

Use numeric IDs when:

  • you want the smallest possible message size
  • your organization can keep IDs stable and globally unique
  • services are tightly coordinated

Use names when:

  • teams define types independently
  • schemas are already identified by package/module name
  • slightly larger metadata overhead is acceptable

Xlang​

For a message to round-trip between JavaScript and another runtime, both sides must use the same identity for a given type: same numeric ID, or same namespace + typeName. See Xlang Serialization.