Skip to content

Instantly share code, notes, and snippets.

@siritori
Created July 9, 2016 03:50
Show Gist options
  • Save siritori/43dde8c04914af0d45baf493548a2c13 to your computer and use it in GitHub Desktop.
Save siritori/43dde8c04914af0d45baf493548a2c13 to your computer and use it in GitHub Desktop.
type updator<T> = (prev: T) => T;
class PartialUpdate<Props>
{
private _props: Props;
protected get props(): Props {
return this._props;
}
constructor(props: Props | updator<Props>, prev?: Props) {
if (typeof props === "function") {
const partial = (props as updator<Props>)(prev) as any;
const prevProps = prev as any;
this._props = Object.getOwnPropertyNames(prev).reduce((acc, key) => {
acc[key] = partial.hasOwnProperty(key) ? partial[key] : prevProps[key];
return acc;
}, {} as any);
} else {
this._props = props as Props;
}
PartialUpdate.deepFreeze(this);
}
protected update<T extends PartialUpdate<Props>>(f: updator<Props>): T {
return new PartialUpdate(f, this.props) as T;
}
private static deepFreeze(o: any) {
Object.freeze(o);
var oIsFunction = typeof o === "function";
var hasOwnProp = Object.prototype.hasOwnProperty;
Object.getOwnPropertyNames(o).forEach(function (prop) {
if (hasOwnProp.call(o, prop)
&& (oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true)
&& o[prop] !== null
&& (typeof o[prop] === "object" || typeof o[prop] === "function")
&& !Object.isFrozen(o[prop])) {
PartialUpdate.deepFreeze(o[prop]);
}
});
}
}
interface TestProps {
hoge?: number;
fuga?: string;
}
class Test extends PartialUpdate<TestProps> {
get hoge(): number {
return this.props.hoge;
}
get fuga() {
return this.props.fuga;
}
public increment(): Test {
return this.update<Test>(prev => ({
hoge: prev.hoge + 1,
}));
}
public add(text: string): Test {
return this.update<Test>(prev => ({
fuga: prev.fuga + text,
}));
}
}
namespace TestFactory {
export function create() {
return new Test({
hoge: 0,
fuga: "",
});
}
}
// usage
const t1 = TestFactory.create();
const t2 = t1.increment().add("ssf").increment().add("adada");
console.log(t2.hoge);
console.log(t2.fuga);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment