Skip to content

Commit

Permalink
feat(ref.ts): add the ref utility class for capturing value
Browse files Browse the repository at this point in the history
  • Loading branch information
DarcyRayner committed Mar 2, 2019
1 parent 83baf63 commit 1d6ce9c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
46 changes: 46 additions & 0 deletions src/core/ref.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Ref } from './ref';

describe('Ref', () => {
it('calls the getter when reading a value', () => {
let localVal = 0;
const ref = new Ref(
() => localVal,
val => {
localVal = val;
}
);
localVal = 10;
expect(ref.value).toBe(10);
});
it('calls the setter when writing a value', () => {
let localVal = 0;
const ref = new Ref(
() => localVal,
val => {
localVal = val;
}
);
ref.value = 10;
expect(localVal).toBe(10);
});

it('can write to a caputured object property', () => {
const obj = {
a: 10,
b: 'hello'
};
const ref = Ref.from(obj, 'a');
ref.value = 12;
expect(obj.a).toBe(12);
});

it('can read from a captured object property', () => {
const obj = {
a: 10,
b: 'hello'
};
const ref = Ref.from(obj, 'b');
obj.b = 'world';
expect(ref.value).toBe('world');
});
});
31 changes: 31 additions & 0 deletions src/core/ref.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* `Ref` captures a variable using closure functions.
*/
export class Ref<T> {
get value(): T {
return this.getter();
}

set value(val: T) {
this.setter(val);
}

/**
* Captures a reference to a property on an object. Setting/getting the value of the resultant `Ref` will read/write
* to the original property.
* @param object The object to capture the reference from.
* @param property The property to capture the reference of.
*/
static from<T, C extends keyof T>(object: T, property: C): Ref<T[C]> {
const getter = () => object[property];
const setter = (val: T[C]) => (object[property] = val);
return new Ref(getter, setter);
}

/**
* Create a new `Ref`.
* @param getter The getter to use for variable access
* @param setter The setter to use for variable assignment;
*/
constructor(private getter: () => T, private setter: (val: T) => void) {}
}

0 comments on commit 1d6ce9c

Please # to comment.