DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 967,611 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Andrew Morris
Andrew Morris

Posted on

How to Speak Binary in TypeScript

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);
Enter fullscreen mode Exit fullscreen mode

JSON is nice for two reasons:

  1. You can read it ({"direction":"up","distance":1000} is pretty explicit).
  2. 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;
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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 }
Enter fullscreen mode Exit fullscreen mode

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)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.