50

Setting up constants via proxies

 5 years ago
source link: https://www.tuicool.com/articles/hit/mayIJbU
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

In this blog post, a describe a little hack for quickly setting up constants (think enum values, but not wrapped inside a namespace). It is more an educational puzzle than something you should actually use in your code.

As an example, consider the following TypeScript enum (JavaScript itself does not have enums):

enum MyEnum { foo, bar, baz }

assert.equal(MyEnum.foo, 0);
assert.equal(MyEnum.bar, 1);
assert.equal(MyEnum.baz, 2);

I usually prefer to use strings as enum values, because they are easier to debug:

enum MyEnum { foo='foo', bar='bar', baz='baz' }

assert.equal(MyEnum.foo, 'foo');
assert.equal(MyEnum.bar, 'bar');
assert.equal(MyEnum.baz, 'baz');

A pure JavaScript solution

You can achieve something similar in JavaScript as follows.

const keyProxy = new Proxy({}, {
  get(_target, propKey, _receiver) {
    return propKey;
  }
});
const {foo, bar, baz} = keyProxy;

assert.equal(foo, 'foo');
assert.equal(bar, 'bar');
assert.equal(baz, 'baz');

How does it work? We combine two ingredients to achieve this effect.

First, the proxy is an object where, whatever key you use to read a property, you always get that key as a value:

assert.equal(keyProxy.hello, 'hello');
assert.equal(keyProxy.world, 'world');

Second, using property value shorthands during destructuring lets us specify both a property key and a variable name at the same time. That is, the following two declarations are equivalent.

const {foo, bar, baz} = keyProxy;
const {foo: foo, bar: bar, baz: baz} = keyProxy;

Symbols as values for the constants

If you use symbols as values for the constants, you get more type safety. The only line of the proxy that changes is line A.

const keyProxy = new Proxy({}, {
  get(_target, propKey, _receiver) {
    return Symbol(propKey); // (A)
  }
});
const {foo, bar, baz} = keyProxy;

assert.equal(typeof foo, 'symbol');
assert.equal(String(foo), 'Symbol(foo)');

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK