A Composite Key could be a symbol instead of an object.
Unlike objects, not all symbols are currently usable as WeakMap keys, which would make it less surprising when the author attempts to use in a weak collection a Composite Key formed only of forgeable values (#3).
Using a symbol does not automatically resolve the question of value-like or unique semantics (#2), however value semantics would be natural for symbols, and more importantly, the author may not have as high expectations for the efficiency of === with complex primitive values. After all, string comparison can already be costly today.
const obj = {};
const a = CompositeKey.for(obj, 1, 2);
const b = CompositeKey.for(obj, 1, 2);
assert(typeof a === "symbol");
assert(a === b);
const ws = new WeakSet();
ws.add(a);
assert(ws.has(b));
assert.throws(() => ws.add(CompositeKey.for(0, 1, 2)));
Unlike registered symbols, there would be no way to get the constituents out of a composite key symbol. E.g. No CompositeKey.componentsFor
Pro: Maps/Sets and WeakMaps/WeakSets don't need to be aware of CompositeKey and treat it differently from other symbols (besides their weakability like for current symbols)
Pro: Does not require interning at the point in time when CKs symbols are created. Any interning could be delayed until ===, with overhead in line with the existing string overhead.
Pro: Does not enforce that at least one constituent has a lifetime. Like other symbols, some can be forgeable, while some are unique.
Con: No intent expressed by the typeof value (unlike the unique object approach which has a prototype).
A Composite Key could be a symbol instead of an object.
Unlike objects, not all symbols are currently usable as WeakMap keys, which would make it less surprising when the author attempts to use in a weak collection a Composite Key formed only of forgeable values (#3).
Using a symbol does not automatically resolve the question of value-like or unique semantics (#2), however value semantics would be natural for symbols, and more importantly, the author may not have as high expectations for the efficiency of
===
with complex primitive values. After all, string comparison can already be costly today.Unlike registered symbols, there would be no way to get the constituents out of a composite key symbol. E.g. No
CompositeKey.componentsFor
Map
s/Set
s andWeakMap
s/WeakSet
s don't need to be aware of CompositeKey and treat it differently from other symbols (besides their weakability like for current symbols)===
, with overhead in line with the existing string overhead.typeof
value (unlike the unique object approach which has a prototype).