TypeScript and Immutability

TypeScript and Immutability

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

Transcript

  1. 17.

    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. 18.

    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. 21.

    interface HumanEntityWriter extends Writer<HumanEntity> {! updateName(name: string): void;! updateAge(age: number):

    void;! }! ! interface HumanEntity extends Writable<HumanEntityWriter> {! name: string;! age: number;! }!
  4. 25.

    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! });! });! }!