Skip to content

Instantly share code, notes, and snippets.

@pgilad pgilad/account.ts
Last active Dec 26, 2018

Embed
What would you like to do?
An example of a model wrapping read only state using Typescript
import _ from 'lodash';
import produce from 'immer';
import { IAccount } from '../../types/account';
import { IData, IModifiable, ProduceRecipe } from '../metadata';
/**
* An account model
*/
export class Account implements IModifiable<IAccount>, IData<IAccount> {
readonly data: Readonly<IAccount>;
constructor(data: Readonly<IAccount>) {
this.data = data;
}
update(recipe: ProduceRecipe<IAccount>): Account {
return new Account(produce(this.data, recipe));
}
getAccountPlanType() {
return this.data.plan.type || 'credits';
}
getAccountRoles() {
return this.data.activeMember.roles || [];
}
hasRole(role: string) {
const roles = this.getAccountRoles();
return _.includes(roles, role);
}
}
/*
Example usage:
const a = new Account({
id: 1,
owner: {},
features: {
v4Jetpack: false,
v4PipelineDefault: false,
},
plan: {},
billing: {},
activeMember: { id: 1234 },
});
const b = a.update(draft => {
draft.billing.city = 'hello';
draft.activeMember.access = 123;
});
*/
import { Draft } from 'immer';
type InstanceType<D, T> = { data: Readonly<D>; new(data: Readonly<D>): T };
export interface IData<D> {
/**
* The internal immutable state data
*/
readonly data: Readonly<D>;
}
export interface IModifiable<D> {
/**
* An update function to update internal instance data, returning a new instance with the updated data
* @param args The arguments required to transform the data without modifying it
*/
update<T>(this: InstanceType<D, T>, ...args: any[]): T;
}
/**
* Representing the basic immer produce function
*/
export type ProduceRecipe<T> = (draftState: Draft<T>) => void | T;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.