Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TypeScript and Immutability

TypeScript and Immutability

TypeScriptでImmutableなエンティティを表現する方法あれこれ

More Decks by Taketoshi Aono(青野健利 a.k.a brn)

Other Decks in Programming

Transcript

  1. type Primitive = undefined | null | boolean | string

    | number | Function;! ! interface ConstArray<T> extends ReadonlyArray<Const<T>> {}! type ConstObject<T> = {! readonly [P in keyof T]: Const<T[P]>! };! ! type Const<T> = T extends Primitive! ? T! : T extends ConstArray<any>! ? T! : T extends (infer R)[]! ? ConstArray<R>! : T extends object ? ConstObject<T> : T;!
  2. type Mutable<T> = T extends Primitive! ? T! : T

    extends MutableArray<any>! ? T! : T extends (infer R)[]! ? MutableArray<R>! : T extends ConstArray<infer A>! ? MutableArray<A>! : T extends object ? MutableObject<T> : T;! ! interface MutableArray<T> extends Array<Mutable<T>> {}! ! type MutableObject<T> = {! -readonly [P in keyof T]: Mutable<T[P]>! };!
  3. interface HumanEntityWriter extends Writer<HumanEntity> {! updateName(name: string): void;! updateAge(age: number):

    void;! }! ! interface HumanEntity extends Writable<HumanEntityWriter> {! name: string;! age: number;! }!
  4. import produce from 'immer';! function mutate<T extends Writable<U>, U>(! entity:

    T, ! callback: (writer: U) => void! ) {! produce(entity, draft => {! callback({! ...entity._writer,! _target: entity! });! });! }!