Proposal for TypedObject

Using TypedArray instance we are allowed to access and modify raw binary in javascript but limited only in one type per instance, but what if we can group multiple instance of TypedArray in one instance sharing one buffer with different byteOffsets and access as a property defined with getter and setter functions, just like an instance of struct in c++.

TypedObject instance is just a template and constructs an instance of TypedInstance constructor when newInstance function is called.

TypedInstance instances will have buffer, byteOffset and byteLength own properties similar to TypedArray prototype properties.

let point = new TypedObject({
x: "int32",
y: "int32"
});

let p = point.newInstance({
x: 100,
y: 100
});

console.log(p.x, p.y); // 100, 100

TypedArrays are views of an ArrayBuffer. So while each TypedArray is limited to one type , the under lying array can store multiple types.

DataViews can be used to get a view on to the ArrayBuffer which exposes multiple data types at once

https://tc39.es/ecma262/multipage/structured-data.html#sec-dataview-objects

There was recently a suggestion along those lines here: Upgradeable ArrayBuffers ยท Issue #368 ยท tc39/proposal-record-tuple ยท GitHub

The main problem is how to define a reusable schema, especially one that can be passed to other agents when transferring the view / array buffer, and how to encode more complex values like objects, arrays and symbols, or even strings and bigint for that matter, since those don't have a fixed size or representation either.

At this point I'd like to ask what is the problem you're trying to solve. It's possible an approach like GitHub - tc39/proposal-structs: JavaScript Structs: Fixed Layout Objects may be more appropriate. It doesn't have the concept of serializing into an underlying byte array, but it's meant to create a complex struct like value that both JS and WASM can more easily interoperate on.

Main purpose behind this idea is bringing optional typing in javascript without adding new syntax but instead making type represented as object created using function constructors.

For example creating typed class we can define using the following code

const Rectangle = Type.class({
  width_: Type.int,
  height_: Type.int,

  constructor({ width, height }) {
    this.width_ = width;
    this.height_ = height;
  },
  
  getArea() {
    return this.width * this.height;
  }
});

and instantiate using Typed.new

let rect = Type.new(Rectangle, {
  width: 100,
  height: 100
});

Object created using Typed.class is an instance of TypedClass that can be used to construct many instances of itself. This object is frozen and has own properties that described the typed class, template property that holds the object that passed to Type.class function, size property for holding the size of the TypedClass.

Using this approach we can define enum, interface, struct and union

Every instances that created using Type.new returns an instance of TypedInstance that has fixed width object, no properties can be added or removed or configured.

And for implementation of string typed property, this property will be like a pointer where the actual string is stored on memory or on a ArrayBuffer, but when accessing the property it will returned only the string value not the pointer address.

Couldn't you accomplish this with regular classes that validate their properties, example through the upcoming decorators?

Preventing extension is a little more complicated to do if you want to support inheritance, but if not, a simple Object.seal would do.

I don't see why muddle things with a backing byte buffer.