1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | function 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 |
|
71 | module.exports = namedTuple;
|