Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ebi
Last active April 19, 2017 07:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ebi/d186c4297c84d562aeae to your computer and use it in GitHub Desktop.
Save ebi/d186c4297c84d562aeae to your computer and use it in GitHub Desktop.
export class Immutable<S> {
private obj: S;
constructor(obj: S) {
Object.freeze(obj);
if (typeof obj === 'object') {
Object.keys(obj).forEach((key: string): void => {
Object.freeze(obj[key]);
});
}
this.obj = obj;
}
get v(): S {
return this.obj;
}
set(f: (objCopy: S) => S): Immutable<S> {
let objCopy: S;
if (Array.isArray(this.obj)) {
objCopy = (<any>this.obj).slice();
} else if (typeof this.obj === 'object') {
objCopy = Object.assign({}, this.obj);
} else {
objCopy = this.obj;
}
return new Immutable(f(objCopy));
}
}
import {Immutable} from './immutable';
import {Person} from './simple';
type GangMember = Immutable<Person>;
interface Gang {
sign: string;
assets: string[];
members: Immutable<GangMember[]>;
}
let gang: Immutable<Gang>;
let member1 = new Immutable({ name: 'John', height: 1337 });
let member2 = new Immutable({ name: 'Doe', height: 42 })''
gang = new Immutable<Gang>({
sign: 'frontend',
assets: ['tags'],
members: new Immutable([
member1,
member2
]),
});
let homer = new Immutable({ name: 'Homer', height: 110 });
console.log(gang.v.assets.length) // 1
try {
gang.v.assets.push('attributes');
} catch (e) {
// TypeError: Can't add property "attributes", object is not extensible
}
console.log(gang.v.assets.length) // 1
console.log(gang.v.members.v.length); // 2
gang = gang.set((gang: Gang): Gang => {
gang.members = gang.members.set((members: GangMember[]): GangMember[] => {
members.push(homer);
return members;
});
return gang;
});
console.log(gang.v.members.v.length); // 3
console.log(gang.v.members.v[0] === member1); // true
console.log(gang.v.members.v[2].v.name); // Homer
homer.v.name = 'Bart';
console.log(gang.v.members.v[2].v.name); // Homer
gang = gang.set((gang: Gang): Gang => {
gang.members = gang.members.set((members: GangMember[]): GangMember[] => {
members.push(homer);
members[2] = members[2].set((member: Person): Person => {
member.name = 'Bart';
return member;
});
return members;
});
return gang;
});
console.log(gang.v.members.v[2].v.name); // Bart
import {Immutable} from './immutable';
export interface Person {
name: string;
height: number;
}
let person: Immutable<Person>;
person = new Immutable({
name: 'John',
height: 1337,
});
console.log(person.v.name); // John
person.v.name = 'Doe';
console.log(person.v.name); // John
person = person.set((person: Person): Person => {
person.name = 'Doe';
return person;
});
console.log(person.v.name); // Doe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment