UNPKG

1.64 kBJavaScriptView Raw
1/**
2 * Make a NamedTuple Class
3 *
4 * @param names {string[]}
5 * @return {NamedTuple}
6 *
7 * @example
8 * > Student = namedTuple('name', 'age')
9 * > student = new Student('Tom', 18)
10 * > Array.isArray(student)
11 true
12 * > student
13 NamedTuple(name,age) [ 'Tom', 18 ]
14 * > student.toObject()
15 { name: 'Tom', age: 18 }
16 * > student.name
17 "Tom"
18 * > student.age
19 18
20 * > student.age = 19
21 Error: can not change element to a NamedTuple
22 */
23function namedTuple(...names) {
24 const _nameToIndex = {};
25 names.forEach((name, index) => {
26 _nameToIndex[name] = index;
27 });
28
29 class NamedTuple extends Array {
30 constructor(...args) {
31 super(...args);
32
33 return new Proxy(this, {
34 has: (_, key) => {
35 const index = _nameToIndex[key];
36 return index !== undefined ? true : (key in this);
37 },
38 get: (_, key) => {
39 const index = _nameToIndex[key];
40 return index === undefined ? this[key] : this[index];
41 },
42 set: () => {
43 throw new Error('can not change element to a NamedTuple');
44 },
45 deleteProperty: () => {
46 throw new Error('can not delete element to a NamedTuple');
47 },
48 });
49 }
50
51 static get name() {
52 return `NamedTuple(${names.join(',')})`;
53 }
54
55 static fromObject(object) {
56 return new this(...names.map(name => object[name]));
57 }
58
59 toObject() {
60 const obj = {};
61 names.forEach(name => {
62 obj[name] = this[name];
63 });
64 return obj;
65 }
66 }
67
68 return NamedTuple;
69}
70
71module.exports = namedTuple;