From 5e4c40bad83d5367463be478aca1a9ffca63f3c5 Mon Sep 17 00:00:00 2001 From: Oliver Heard Date: Thu, 22 Feb 2018 16:28:06 +0000 Subject: [PATCH] Improves type safety in immer.d.ts and fixes 97 - Fixed two-arg produce() curries being returned as one-arg curries - Added a one-arg produce() curry signature - Current state may now be Readonly via new type MaybeReadonly - produce() and curries now return Readonly - Added Draft that ensures the draft is always writable (fixes 97) - Reversed the order of produce() signatures so that the most specific is used first - Added non-doc style comments to curry-producing produce() variants - Added a note to the varadic signature of produce() about Typescript issue 5453 --- src/immer.d.ts | 45 ++++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/immer.d.ts b/src/immer.d.ts index 17aec72f..3c0d4950 100644 --- a/src/immer.d.ts +++ b/src/immer.d.ts @@ -1,3 +1,6 @@ +export type MaybeReadonly = T|Readonly +export type Draft = { [P in keyof T]: T[P] } + /** * Immer takes a state, and runs a function against it. * That function can freely mutate the state, as it will create copies-on-write. @@ -11,22 +14,38 @@ * @returns The next state: a new state, or the current state if nothing was modified */ export default function( - currentState: S, - recipe: (this: S, draftState: S) => void -): S + currentState: MaybeReadonly, + recipe: (this: Readonly, draftState: Draft) => void +): Readonly + // curried invocations -export default function( - recipe: (this: S, draftState: S, a: A, b: B, c: C) => void -): (currentState: S, a: A, b: B, c: C) => S -export default function( - recipe: (this: S, draftState: S, a: A, b: B) => void -): (currentState: S, a: A, b: B) => S + +// 0 additional arguments +export default function( + recipe: (this: Readonly, draftState: Draft) => void +): (currentState: MaybeReadonly) => Readonly + +// 1 additional argument of type A export default function( - recipe: (this: S, draftState: S, a: A) => void -): (currentState: S) => S + recipe: (this: Readonly, draftState: Draft, a: A) => void +): (currentState: MaybeReadonly, a: A) => Readonly + +// 2 additional arguments of types A and B +export default function( + recipe: (this: Readonly, draftState: Draft, a: A, b: B) => void +): (currentState: MaybeReadonly, a: A, b: B) => Readonly + +// 3 additional arguments of types A, B and C +export default function( + recipe: (this: Readonly, draftState: Draft, a: A, b: B, c: C) => void +): (currentState: MaybeReadonly, a: A, b: B, c: C) => Readonly + +// any number of additional arguments, but with loss of type safety +// this may be alleviated if "variadic kinds" makes it into Typescript: +// https://github.com/Microsoft/TypeScript/issues/5453 export default function( - recipe: (this: S, draftState: S, ...extraArgs: any[]) => void -): (currentState: S, ...extraArgs: any[]) => S + recipe: (this: Readonly, draftState: Draft, ...extraArgs: any[]) => void +): (currentState: MaybeReadonly, ...extraArgs: any[]) => Readonly /** * Automatically freezes any state trees generated by immer.