'"Herding" objects by "value branding" in Typescript

Is it possible in Typescript to transfer the uniqueness of a Symbol() to a container type and from there to the objects stored therein such that objects stored in one instance of the container type cannot be stored in another? Something like this is pretty close:

class Branded<T, B> {
  constructor(readonly value: T, readonly brand: B) {}
}
class Container<T, B extends symbol> {
  // mark the container with a symbol
  constructor(readonly brand: B) {}
  // somehow get a branded T out of the container
  getOrCreate(...): Branded<T, B> {...}
  // store only Branded values
  // the goal would be to allow only values that were handed out of
  // this particular object, but see below
  store(v: Branded<T, B>): void {...}
}
// create two containers from the same symbol
const brand = Symbol();
const c1 = new Container(brand);
const c2 = new Container(brand);
// cannot avoid that this works, but it should not:
c1.store(c2.getOrCreate(...));

Is there a chance to let the compiler complain on the last line. The goal is that a Container object is as unique as a symbol and "herds" only the Branded values it hands out, with no intermingling with values from other containers. It seems to require that the symbol in brand can only be used once or that it is internal to Container.

See typescript playground.



Solution 1:[1]

The solution I found is a bit of a workaround, but sufficiently practical to be used.

  1. Make the constructor of Container private.
  2. Provide a static factory method which returns always the same Container for a given brand by keeping a static Map from brand symbols to Container objects.

The name of the method and its documentation should make clear that a "singleton" per brand is returned, i.e. all invocations with the same brand symbol will return one and the same instance.

I call this "a bit of a workaround", because the compiler will still not complain in the last line as asked for, but now it is inconsequential since both variables from the question, c1 and c2, reference the same container object. Objects "herded" by one container are not entering a different one.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Harald