js-conflux-sdk
Version:
JavaScript Conflux Software Development Kit
74 lines (66 loc) • 1.71 kB
JavaScript
/**
* Make a NamedTuple Class
* @typedef {Object} NamedTuple
* @template NamedTuple
* @param {string[]} names
* @returns {NamedTuple}
*
* @example
* > Student = namedTuple('name', 'age')
* > student = new Student('Tom', 18)
* > Array.isArray(student)
true
* > student
NamedTuple(name,age) [ 'Tom', 18 ]
* > student.toObject()
{ name: 'Tom', age: 18 }
* > student.name
"Tom"
* > student.age
18
* > student.age = 19
Error: can not change element to a NamedTuple
*/
function namedTuple(...names) {
const _nameToIndex = {};
names.forEach((name, index) => {
_nameToIndex[name] = index;
});
class NamedTuple extends Array {
constructor(...args) {
super(args.length);
args.forEach((v, i) => Reflect.set(this, i, v)); // XXX: new Array(0) === []
return new Proxy(this, {
has: (_, key) => {
const index = _nameToIndex[key];
return index !== undefined ? true : (key in this);
},
get: (_, key) => {
const index = _nameToIndex[key];
return index === undefined ? this[key] : this[index];
},
set: () => {
throw new Error('can not change element to a NamedTuple');
},
deleteProperty: () => {
throw new Error('can not delete element to a NamedTuple');
},
});
}
static get name() {
return `NamedTuple(${names.join(',')})`;
}
static fromObject(object) {
return new this(...names.map(name => object[name]));
}
toObject() {
const obj = {};
names.forEach(name => {
obj[name] = this[name];
});
return obj;
}
}
return NamedTuple;
}
module.exports = namedTuple;