If you're sending or receiving data in TypeScript, chances are high that you are using JSON:
const awesomeData = {
direction: 'up',
distance: 1000,
};
const json = JSON.stringify(awesomeData);
send(json);
JSON is nice for two reasons:
- You can read it (
{"direction":"up","distance":1000}
is pretty explicit). - JSON doesn't take anything to set up, it's just there.
However, this simple utility doesn't play very nicely with TypeScript:
const json = receive();
// { direction:'up', distance: 1000 }
const awesomeData = JSON.parse(json);
// TypeScript compiler: "Sure, why not?"
awesomeData.direction = 1;
JSON.parse
is one of those APIs that opts out of type checking - it returns any
, which means TypeScript knows nothing about it, but will let us do anything with it.
That's not cool. We're using TypeScript to avoid exactly this problem.
There is a better way:
import * as tb from 'typed-bytes';
const Awesome = tb.object({
direction: tb.enum_('up', 'down', 'left', 'right'),
distance: tb.size,
});
type Awesome = tb.TypeOf<typeof Awesome>;
function sendData() {
const awesomeData: Awesome = {
direction: 'up',
distance: 1000,
};
// Here encodeBuffer knows that awesomeData needs to match type Awesome
const buffer = tb.encodeBuffer(Awesome, awesomeData);
send(buffer);
}
function receiveData() {
const buffer = receive();
const awesomeData = tb.decodeBuffer(Awesome, buffer);
// Error: Type '1' is not assignable to type '"up" | "down" | "left" | "right"'
awesomeData.direction += 1;
}
Hooray, now awesomeData
is correctly type checked 🎉.
It's not just that though. Take a closer look at buffer
:
ArrayBuffer { [Uint8Contents]: <00 e8 07>, byteLength: 3 }
Three bytes. That's all we needed. In JSON we used 34 bytes.
Why not just use Protocol Buffers?
I'm glad you asked. typed-bytes
is a public domain library that lives at typedbytes.org. There's a detailed comparison over there 😉.
Top comments (0)