Skip to content

Instantly share code, notes, and snippets.

@joakim
Last active December 28, 2021 19:48
Show Gist options
  • Save joakim/78c8c3596f3b00cbac8da2eb22257c03 to your computer and use it in GitHub Desktop.
Save joakim/78c8c3596f3b00cbac8da2eb22257c03 to your computer and use it in GitHub Desktop.
Collection – a tiny, immutable data structure for JavaScript/TypeScript
Collection = (spec) => {
if (typeof spec !== 'object') throw new TypeError('Collection specification must be an object')
return Object.freeze(Object.create(Collection.prototype, Object.getOwnPropertyDescriptors(spec)))
}
Collection.prototype = Object.create(null, {
[Symbol.isConcatSpreadable]: { value: true },
[Symbol.iterator]: { value: function* () { for (let key in this) { yield this[key] } } },
[Symbol.toPrimitive]: { value: (hint) => hint === 'number' ? NaN : '[object Collection]' },
[Symbol.toStringTag]: { value: 'Collection' },
})
// Keyed collection
keyed = Collection({ foo: 42, bar: true })
keyed.foo // 42
keyed.bar // true
Object.keys(arrayish) // [ "foo", "bar" ]
Object.values(arrayish) // [ 42, true ]
({ foo, bar } = keyed) // foo = 42, bar = true
[first, second] = keyed // first = 42, second = true
// Indexed collection
indexed = Collection({ 0: 42, 1: true })
indexed[0] // 42
indexed[1] // true
Object.keys(indexed) // [ "0", "1" ]
Object.values(indexed) // [ 42, true ]
[first, second] = indexed // first = 42, second = true
({ 0: first, 1: second } = indexed) // first = 42, second = true
// Mixed collection (Array-like)
arrayish = Collection([42, true])
arrayish[0] // 42
arrayish[1] // true
arrayish.length // 2
Object.keys(arrayish) // [ "0", "1", "length" ]
Object.values(arrayish) // [ 42, true, 3 ]
[first, second] = arrayish // first = 42, second = true
({ length } = arrayish) // length = 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment