Last active
December 26, 2018 07:34
-
-
Save pgilad/3d6e6b30600471541ea288a0068f530b to your computer and use it in GitHub Desktop.
An example of a model wrapping read only state using Typescript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}); | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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