Skip to content

Objects

Primitive values in JavaScript can be composed into Plain-Old-JavaScript-Objects. This can be easily represented using the bin.struct() schema constructor function.

import * as bin from 'typed-binary';
// Simple object schema
const Person = bin.struct({
firstName: bin.string,
lastName: bin.string,
age: bin.i32,
});
// Writing a Person
Person.write(writer, {
firstName: 'John',
lastName: 'Doe',
age: 43,
});
console.log(JSON.stringify(Person.read(reader))); // { "firstName": "John", ... }

The type of values a struct reads can be extracted with bin.ExtractOut, and the type of values it accepts when writing with bin.ExtractIn. The latter is a readonly version of the former, so that readonly data can be written too.

type Person = bin.ExtractOut<typeof Person>;
// ^? { firstName: string, lastName: string, age: number }

bin.concat creates a struct with the properties of all the passed in structs, in order.

const Employee = bin.concat([Person, bin.struct({ salary: bin.u32 })]);
// { firstName: string, lastName: string, age: number, salary: number }

bin.union describes a value that can take one of several shapes (variants), depending on a tag that is encoded before it. For example, if you want to store an animal description, certain animal types might have differing features from one another.

import * as bin from 'typed-binary';
const Animal = bin.union(
// The tag, encoded first
bin.orderedEnum('dog', 'cat'),
// The properties of each variant, keyed by the value of the tag
{
dog: { breed: bin.string },
cat: { striped: bin.bool },
},
// Properties shared by all variants, encoded right after the tag
{ base: { nickname: bin.string, age: bin.i32 } },
);
// Writing an Animal
Animal.write(writer, {
type: 'cat', // We're specifying which variant we want this object to be.
// Base properties
nickname: 'James',
age: 5,
// Variant specific properties
striped: true,
});
// Deserializing the animal
const animal = Animal.read(reader);
// -- Type checking works here! --
// animal.type => 'dog' | 'cat'
if (animal.type === 'cat') {
// animal.striped => boolean
console.log(animal.striped ? 'Striped' : 'Not striped');
} else {
// animal.breed => string
console.log(`More specifically, a ${animal.breed}`);
// This would result in a type error (Static typing FTW!)
// console.log(`Striped: ${animal.striped}`);
}

The tag can be any schema whose values key the variants:

Tag Encoding
bin.orderedEnum('dog', 'cat') The index of the value, in a single byte
bin.prefixEnum('dog', 'cat') The ASCII characters of the value
bin.u8, bin.u16, … The number itself, e.g. for variants keyed by a TypeScript enum
bin.string A null-terminated string

The property holding the tag is called type by default, and can be renamed with the key option: bin.union(tag, variants, { key: 'kind' }).