You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

117 lines
4.9 KiB

  1. // Mapped type to remove readonly modifiers from state
  2. // Based on https://github.com/Microsoft/TypeScript/blob/d4dc67aab233f5a8834dff16531baf99b16fea78/tests/cases/conformance/types/conditional/conditionalTypes1.ts#L120-L129
  3. export type DraftObject<T> = {
  4. -readonly [P in keyof T]: Draft<T[P]>;
  5. };
  6. export interface DraftArray<T> extends Array<Draft<T>> { }
  7. export type Draft<T> =
  8. T extends any[] ? DraftArray<T[number]> :
  9. T extends ReadonlyArray<any> ? DraftArray<T[number]> :
  10. T extends object ? DraftObject<T> :
  11. T;
  12. export interface Patch {
  13. op: "replace" | "remove" | "add",
  14. path: (string|number)[]
  15. value?: any
  16. }
  17. export type PatchListener = (patches: Patch[], inversePatches: Patch[]) => void
  18. export interface IProduce {
  19. /**
  20. * Immer takes a state, and runs a function against it.
  21. * That function can freely mutate the state, as it will create copies-on-write.
  22. * This means that the original state will stay unchanged, and once the function finishes, the modified state is returned.
  23. *
  24. * If the first argument is a function, this is interpreted as the recipe, and will create a curried function that will execute the recipe
  25. * any time it is called with the current state.
  26. *
  27. * @param currentState - the state to start with
  28. * @param recipe - function that receives a proxy of the current state as first argument and which can be freely modified
  29. * @param initialState - if a curried function is created and this argument was given, it will be used as fallback if the curried function is called with a state of undefined
  30. * @returns The next state: a new state, or the current state if nothing was modified
  31. */
  32. <S = any>(
  33. currentState: S,
  34. recipe: (this: Draft<S>, draftState: Draft<S>) => void | S,
  35. listener?: PatchListener
  36. ): S
  37. // curried invocations with default initial state
  38. // 0 additional arguments
  39. <S = any>(
  40. recipe: (this: Draft<S>, draftState: Draft<S>) => void | S,
  41. initialState: S
  42. ): (currentState: S | undefined) => S
  43. // 1 additional argument of type A
  44. <S = any, A = any>(
  45. recipe: (this: Draft<S>, draftState: Draft<S>, a: A) => void | S,
  46. initialState: S
  47. ): (currentState: S | undefined, a: A) => S
  48. // 2 additional arguments of types A and B
  49. <S = any, A = any, B = any>(
  50. recipe: (this: Draft<S>, draftState: Draft<S>, a: A, b: B) => void | S,
  51. initialState: S
  52. ): (currentState: S | undefined, a: A, b: B) => S
  53. // 3 additional arguments of types A, B and C
  54. <S = any, A = any, B = any, C = any>(
  55. recipe: (this: Draft<S>, draftState: Draft<S>, a: A, b: B, c: C) => void | S,
  56. initialState: S
  57. ): (currentState: S | undefined, a: A, b: B, c: C) => S
  58. // any number of additional arguments, but with loss of type safety
  59. // this may be alleviated if "variadic kinds" makes it into Typescript:
  60. // https://github.com/Microsoft/TypeScript/issues/5453
  61. <S = any>(
  62. recipe: (this: Draft<S>, draftState: Draft<S>, ...extraArgs: any[]) => void | S,
  63. initialState: S
  64. ): (currentState: S | undefined, ...extraArgs: any[]) => S
  65. // curried invocations without default initial state
  66. // 0 additional arguments
  67. <S = any>(
  68. recipe: (this: Draft<S>, draftState: Draft<S>) => void | S
  69. ): (currentState: S) => S
  70. // 1 additional argument of type A
  71. <S = any, A = any>(
  72. recipe: (this: Draft<S>, draftState: Draft<S>, a: A) => void | S
  73. ): (currentState: S, a: A) => S
  74. // 2 additional arguments of types A and B
  75. <S = any, A = any, B = any>(
  76. recipe: (this: Draft<S>, draftState: Draft<S>, a: A, b: B) => void | S
  77. ): (currentState: S, a: A, b: B) => S
  78. // 3 additional arguments of types A, B and C
  79. <S = any, A = any, B = any, C = any>(
  80. recipe: (this: Draft<S>, draftState: Draft<S>, a: A, b: B, c: C) => void | S
  81. ): (currentState: S, a: A, b: B, c: C) => S
  82. // any number of additional arguments, but with loss of type safety
  83. // this may be alleviated if "variadic kinds" makes it into Typescript:
  84. // https://github.com/Microsoft/TypeScript/issues/5453
  85. <S = any>(
  86. recipe: (this: Draft<S>, draftState: Draft<S>, ...extraArgs: any[]) => void | S
  87. ): (currentState: S, ...extraArgs: any[]) => S
  88. }
  89. export const produce: IProduce
  90. export default produce
  91. export const nothing: undefined
  92. /**
  93. * Automatically freezes any state trees generated by immer.
  94. * This protects against accidental modifications of the state tree outside of an immer function.
  95. * This comes with a performance impact, so it is recommended to disable this option in production.
  96. * It is by default enabled.
  97. */
  98. export function setAutoFreeze(autoFreeze: boolean): void
  99. /**
  100. * Manually override whether proxies should be used.
  101. * By default done by using feature detection
  102. */
  103. export function setUseProxies(useProxies: boolean): void
  104. export function applyPatches<S>(state: S, patches: Patch[]): S
  105. export function original<T>(value: T): T | void