| 1 | /**
|
|---|
| 2 | * The sentinel value returned by producers to replace the draft with undefined.
|
|---|
| 3 | */
|
|---|
| 4 | declare const NOTHING: unique symbol;
|
|---|
| 5 | /**
|
|---|
| 6 | * To let Immer treat your class instances as plain immutable objects
|
|---|
| 7 | * (albeit with a custom prototype), you must define either an instance property
|
|---|
| 8 | * or a static property on each of your custom classes.
|
|---|
| 9 | *
|
|---|
| 10 | * Otherwise, your class instance will never be drafted, which means it won't be
|
|---|
| 11 | * safe to mutate in a produce callback.
|
|---|
| 12 | */
|
|---|
| 13 | declare const DRAFTABLE: unique symbol;
|
|---|
| 14 |
|
|---|
| 15 | type AnyFunc = (...args: any[]) => any;
|
|---|
| 16 | type PrimitiveType = number | string | boolean;
|
|---|
| 17 | /** Object types that should never be mapped */
|
|---|
| 18 | type AtomicObject = Function | Promise<any> | Date | RegExp;
|
|---|
| 19 | /**
|
|---|
| 20 | * If the lib "ES2015.Collection" is not included in tsconfig.json,
|
|---|
| 21 | * types like ReadonlyArray, WeakMap etc. fall back to `any` (specified nowhere)
|
|---|
| 22 | * or `{}` (from the node types), in both cases entering an infinite recursion in
|
|---|
| 23 | * pattern matching type mappings
|
|---|
| 24 | * This type can be used to cast these types to `void` in these cases.
|
|---|
| 25 | */
|
|---|
| 26 | type IfAvailable<T, Fallback = void> = true | false extends (T extends never ? true : false) ? Fallback : keyof T extends never ? Fallback : T;
|
|---|
| 27 | /**
|
|---|
| 28 | * These should also never be mapped but must be tested after regular Map and
|
|---|
| 29 | * Set
|
|---|
| 30 | */
|
|---|
| 31 | type WeakReferences = IfAvailable<WeakMap<any, any>> | IfAvailable<WeakSet<any>>;
|
|---|
| 32 | type WritableDraft<T> = {
|
|---|
| 33 | -readonly [K in keyof T]: Draft<T[K]>;
|
|---|
| 34 | };
|
|---|
| 35 | /** Convert a readonly type into a mutable type, if possible */
|
|---|
| 36 | type Draft<T> = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap<infer K, infer V> ? Map<Draft<K>, Draft<V>> : T extends ReadonlySet<infer V> ? Set<Draft<V>> : T extends WeakReferences ? T : T extends object ? WritableDraft<T> : T;
|
|---|
| 37 | /** Convert a mutable type into a readonly type */
|
|---|
| 38 | type Immutable<T> = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<Immutable<K>, Immutable<V>> : T extends ReadonlySet<infer V> ? ReadonlySet<Immutable<V>> : T extends WeakReferences ? T : T extends object ? {
|
|---|
| 39 | readonly [K in keyof T]: Immutable<T[K]>;
|
|---|
| 40 | } : T;
|
|---|
| 41 | interface Patch {
|
|---|
| 42 | op: "replace" | "remove" | "add";
|
|---|
| 43 | path: (string | number)[];
|
|---|
| 44 | value?: any;
|
|---|
| 45 | }
|
|---|
| 46 | type PatchListener = (patches: Patch[], inversePatches: Patch[]) => void;
|
|---|
| 47 | /**
|
|---|
| 48 | * Utility types
|
|---|
| 49 | */
|
|---|
| 50 | type PatchesTuple<T> = readonly [T, Patch[], Patch[]];
|
|---|
| 51 | type ValidRecipeReturnType<State> = State | void | undefined | (State extends undefined ? typeof NOTHING : never);
|
|---|
| 52 | type ReturnTypeWithPatchesIfNeeded<State, UsePatches extends boolean> = UsePatches extends true ? PatchesTuple<State> : State;
|
|---|
| 53 | /**
|
|---|
| 54 | * Core Producer inference
|
|---|
| 55 | */
|
|---|
| 56 | type InferRecipeFromCurried<Curried> = Curried extends (base: infer State, ...rest: infer Args) => any ? ReturnType<Curried> extends State ? (draft: Draft<State>, ...rest: Args) => ValidRecipeReturnType<Draft<State>> : never : never;
|
|---|
| 57 | type InferInitialStateFromCurried<Curried> = Curried extends (base: infer State, ...rest: any[]) => any ? State : never;
|
|---|
| 58 | type InferCurriedFromRecipe<Recipe, UsePatches extends boolean> = Recipe extends (draft: infer DraftState, ...args: infer RestArgs) => any ? ReturnType<Recipe> extends ValidRecipeReturnType<DraftState> ? (base: Immutable<DraftState>, ...args: RestArgs) => ReturnTypeWithPatchesIfNeeded<DraftState, UsePatches> : never : never;
|
|---|
| 59 | type InferCurriedFromInitialStateAndRecipe<State, Recipe, UsePatches extends boolean> = Recipe extends (draft: Draft<State>, ...rest: infer RestArgs) => ValidRecipeReturnType<State> ? (base?: State | undefined, ...args: RestArgs) => ReturnTypeWithPatchesIfNeeded<State, UsePatches> : never;
|
|---|
| 60 | /**
|
|---|
| 61 | * The `produce` function takes a value and a "recipe function" (whose
|
|---|
| 62 | * return value often depends on the base state). The recipe function is
|
|---|
| 63 | * free to mutate its first argument however it wants. All mutations are
|
|---|
| 64 | * only ever applied to a __copy__ of the base state.
|
|---|
| 65 | *
|
|---|
| 66 | * Pass only a function to create a "curried producer" which relieves you
|
|---|
| 67 | * from passing the recipe function every time.
|
|---|
| 68 | *
|
|---|
| 69 | * Only plain objects and arrays are made mutable. All other objects are
|
|---|
| 70 | * considered uncopyable.
|
|---|
| 71 | *
|
|---|
| 72 | * Note: This function is __bound__ to its `Immer` instance.
|
|---|
| 73 | *
|
|---|
| 74 | * @param {any} base - the initial state
|
|---|
| 75 | * @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified
|
|---|
| 76 | * @param {Function} patchListener - optional function that will be called with all the patches produced here
|
|---|
| 77 | * @returns {any} a new state, or the initial state if nothing was modified
|
|---|
| 78 | */
|
|---|
| 79 | interface IProduce {
|
|---|
| 80 | /** Curried producer that infers the recipe from the curried output function (e.g. when passing to setState) */
|
|---|
| 81 | <Curried>(recipe: InferRecipeFromCurried<Curried>, initialState?: InferInitialStateFromCurried<Curried>): Curried;
|
|---|
| 82 | /** Curried producer that infers curried from the recipe */
|
|---|
| 83 | <Recipe extends AnyFunc>(recipe: Recipe): InferCurriedFromRecipe<Recipe, false>;
|
|---|
| 84 | /** Curried producer that infers curried from the State generic, which is explicitly passed in. */
|
|---|
| 85 | <State>(recipe: (state: Draft<State>, initialState: State) => ValidRecipeReturnType<State>): (state?: State) => State;
|
|---|
| 86 | <State, Args extends any[]>(recipe: (state: Draft<State>, ...args: Args) => ValidRecipeReturnType<State>, initialState: State): (state?: State, ...args: Args) => State;
|
|---|
| 87 | <State>(recipe: (state: Draft<State>) => ValidRecipeReturnType<State>): (state: State) => State;
|
|---|
| 88 | <State, Args extends any[]>(recipe: (state: Draft<State>, ...args: Args) => ValidRecipeReturnType<State>): (state: State, ...args: Args) => State;
|
|---|
| 89 | /** Curried producer with initial state, infers recipe from initial state */
|
|---|
| 90 | <State, Recipe extends Function>(recipe: Recipe, initialState: State): InferCurriedFromInitialStateAndRecipe<State, Recipe, false>;
|
|---|
| 91 | /** Normal producer */
|
|---|
| 92 | <Base, D = Draft<Base>>(// By using a default inferred D, rather than Draft<Base> in the recipe, we can override it.
|
|---|
| 93 | base: Base, recipe: (draft: D) => ValidRecipeReturnType<D>, listener?: PatchListener): Base;
|
|---|
| 94 | }
|
|---|
| 95 | /**
|
|---|
| 96 | * Like `produce`, but instead of just returning the new state,
|
|---|
| 97 | * a tuple is returned with [nextState, patches, inversePatches]
|
|---|
| 98 | *
|
|---|
| 99 | * Like produce, this function supports currying
|
|---|
| 100 | */
|
|---|
| 101 | interface IProduceWithPatches {
|
|---|
| 102 | <Recipe extends AnyFunc>(recipe: Recipe): InferCurriedFromRecipe<Recipe, true>;
|
|---|
| 103 | <State, Recipe extends Function>(recipe: Recipe, initialState: State): InferCurriedFromInitialStateAndRecipe<State, Recipe, true>;
|
|---|
| 104 | <Base, D = Draft<Base>>(base: Base, recipe: (draft: D) => ValidRecipeReturnType<D>, listener?: PatchListener): PatchesTuple<Base>;
|
|---|
| 105 | }
|
|---|
| 106 | /**
|
|---|
| 107 | * The type for `recipe function`
|
|---|
| 108 | */
|
|---|
| 109 | type Producer<T> = (draft: Draft<T>) => ValidRecipeReturnType<Draft<T>>;
|
|---|
| 110 |
|
|---|
| 111 | type Objectish = AnyObject | AnyArray | AnyMap | AnySet;
|
|---|
| 112 | type AnyObject = {
|
|---|
| 113 | [key: string]: any;
|
|---|
| 114 | };
|
|---|
| 115 | type AnyArray = Array<any>;
|
|---|
| 116 | type AnySet = Set<any>;
|
|---|
| 117 | type AnyMap = Map<any, any>;
|
|---|
| 118 |
|
|---|
| 119 | /** Returns true if the given value is an Immer draft */
|
|---|
| 120 | declare function isDraft(value: any): boolean;
|
|---|
| 121 | /** Returns true if the given value can be drafted by Immer */
|
|---|
| 122 | declare function isDraftable(value: any): boolean;
|
|---|
| 123 | /** Get the underlying object that is represented by the given draft */
|
|---|
| 124 | declare function original<T>(value: T): T | undefined;
|
|---|
| 125 | /**
|
|---|
| 126 | * Freezes draftable objects. Returns the original object.
|
|---|
| 127 | * By default freezes shallowly, but if the second argument is `true` it will freeze recursively.
|
|---|
| 128 | *
|
|---|
| 129 | * @param obj
|
|---|
| 130 | * @param deep
|
|---|
| 131 | */
|
|---|
| 132 | declare function freeze<T>(obj: T, deep?: boolean): T;
|
|---|
| 133 |
|
|---|
| 134 | interface ProducersFns {
|
|---|
| 135 | produce: IProduce;
|
|---|
| 136 | produceWithPatches: IProduceWithPatches;
|
|---|
| 137 | }
|
|---|
| 138 | type StrictMode = boolean | "class_only";
|
|---|
| 139 | declare class Immer implements ProducersFns {
|
|---|
| 140 | autoFreeze_: boolean;
|
|---|
| 141 | useStrictShallowCopy_: StrictMode;
|
|---|
| 142 | useStrictIteration_: boolean;
|
|---|
| 143 | constructor(config?: {
|
|---|
| 144 | autoFreeze?: boolean;
|
|---|
| 145 | useStrictShallowCopy?: StrictMode;
|
|---|
| 146 | useStrictIteration?: boolean;
|
|---|
| 147 | });
|
|---|
| 148 | /**
|
|---|
| 149 | * The `produce` function takes a value and a "recipe function" (whose
|
|---|
| 150 | * return value often depends on the base state). The recipe function is
|
|---|
| 151 | * free to mutate its first argument however it wants. All mutations are
|
|---|
| 152 | * only ever applied to a __copy__ of the base state.
|
|---|
| 153 | *
|
|---|
| 154 | * Pass only a function to create a "curried producer" which relieves you
|
|---|
| 155 | * from passing the recipe function every time.
|
|---|
| 156 | *
|
|---|
| 157 | * Only plain objects and arrays are made mutable. All other objects are
|
|---|
| 158 | * considered uncopyable.
|
|---|
| 159 | *
|
|---|
| 160 | * Note: This function is __bound__ to its `Immer` instance.
|
|---|
| 161 | *
|
|---|
| 162 | * @param {any} base - the initial state
|
|---|
| 163 | * @param {Function} recipe - function that receives a proxy of the base state as first argument and which can be freely modified
|
|---|
| 164 | * @param {Function} patchListener - optional function that will be called with all the patches produced here
|
|---|
| 165 | * @returns {any} a new state, or the initial state if nothing was modified
|
|---|
| 166 | */
|
|---|
| 167 | produce: IProduce;
|
|---|
| 168 | produceWithPatches: IProduceWithPatches;
|
|---|
| 169 | createDraft<T extends Objectish>(base: T): Draft<T>;
|
|---|
| 170 | finishDraft<D extends Draft<any>>(draft: D, patchListener?: PatchListener): D extends Draft<infer T> ? T : never;
|
|---|
| 171 | /**
|
|---|
| 172 | * Pass true to automatically freeze all copies created by Immer.
|
|---|
| 173 | *
|
|---|
| 174 | * By default, auto-freezing is enabled.
|
|---|
| 175 | */
|
|---|
| 176 | setAutoFreeze(value: boolean): void;
|
|---|
| 177 | /**
|
|---|
| 178 | * Pass true to enable strict shallow copy.
|
|---|
| 179 | *
|
|---|
| 180 | * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
|
|---|
| 181 | */
|
|---|
| 182 | setUseStrictShallowCopy(value: StrictMode): void;
|
|---|
| 183 | /**
|
|---|
| 184 | * Pass false to use faster iteration that skips non-enumerable properties
|
|---|
| 185 | * but still handles symbols for compatibility.
|
|---|
| 186 | *
|
|---|
| 187 | * By default, strict iteration is enabled (includes all own properties).
|
|---|
| 188 | */
|
|---|
| 189 | setUseStrictIteration(value: boolean): void;
|
|---|
| 190 | shouldUseStrictIteration(): boolean;
|
|---|
| 191 | applyPatches<T extends Objectish>(base: T, patches: readonly Patch[]): T;
|
|---|
| 192 | }
|
|---|
| 193 |
|
|---|
| 194 | /** Takes a snapshot of the current state of a draft and finalizes it (but without freezing). This is a great utility to print the current state during debugging (no Proxies in the way). The output of current can also be safely leaked outside the producer. */
|
|---|
| 195 | declare function current<T>(value: T): T;
|
|---|
| 196 |
|
|---|
| 197 | declare function enablePatches(): void;
|
|---|
| 198 |
|
|---|
| 199 | declare function enableMapSet(): void;
|
|---|
| 200 |
|
|---|
| 201 | /**
|
|---|
| 202 | * The `produce` function takes a value and a "recipe function" (whose
|
|---|
| 203 | * return value often depends on the base state). The recipe function is
|
|---|
| 204 | * free to mutate its first argument however it wants. All mutations are
|
|---|
| 205 | * only ever applied to a __copy__ of the base state.
|
|---|
| 206 | *
|
|---|
| 207 | * Pass only a function to create a "curried producer" which relieves you
|
|---|
| 208 | * from passing the recipe function every time.
|
|---|
| 209 | *
|
|---|
| 210 | * Only plain objects and arrays are made mutable. All other objects are
|
|---|
| 211 | * considered uncopyable.
|
|---|
| 212 | *
|
|---|
| 213 | * Note: This function is __bound__ to its `Immer` instance.
|
|---|
| 214 | *
|
|---|
| 215 | * @param {any} base - the initial state
|
|---|
| 216 | * @param {Function} producer - function that receives a proxy of the base state as first argument and which can be freely modified
|
|---|
| 217 | * @param {Function} patchListener - optional function that will be called with all the patches produced here
|
|---|
| 218 | * @returns {any} a new state, or the initial state if nothing was modified
|
|---|
| 219 | */
|
|---|
| 220 | declare const produce: IProduce;
|
|---|
| 221 | /**
|
|---|
| 222 | * Like `produce`, but `produceWithPatches` always returns a tuple
|
|---|
| 223 | * [nextState, patches, inversePatches] (instead of just the next state)
|
|---|
| 224 | */
|
|---|
| 225 | declare const produceWithPatches: IProduceWithPatches;
|
|---|
| 226 | /**
|
|---|
| 227 | * Pass true to automatically freeze all copies created by Immer.
|
|---|
| 228 | *
|
|---|
| 229 | * Always freeze by default, even in production mode
|
|---|
| 230 | */
|
|---|
| 231 | declare const setAutoFreeze: (value: boolean) => void;
|
|---|
| 232 | /**
|
|---|
| 233 | * Pass true to enable strict shallow copy.
|
|---|
| 234 | *
|
|---|
| 235 | * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
|
|---|
| 236 | */
|
|---|
| 237 | declare const setUseStrictShallowCopy: (value: StrictMode) => void;
|
|---|
| 238 | /**
|
|---|
| 239 | * Pass false to use loose iteration that only processes enumerable string properties.
|
|---|
| 240 | * This skips symbols and non-enumerable properties for maximum performance.
|
|---|
| 241 | *
|
|---|
| 242 | * By default, strict iteration is enabled (includes all own properties).
|
|---|
| 243 | */
|
|---|
| 244 | declare const setUseStrictIteration: (value: boolean) => void;
|
|---|
| 245 | /**
|
|---|
| 246 | * Apply an array of Immer patches to the first argument.
|
|---|
| 247 | *
|
|---|
| 248 | * This function is a producer, which means copy-on-write is in effect.
|
|---|
| 249 | */
|
|---|
| 250 | declare const applyPatches: <T extends Objectish>(base: T, patches: readonly Patch[]) => T;
|
|---|
| 251 | /**
|
|---|
| 252 | * Create an Immer draft from the given base state, which may be a draft itself.
|
|---|
| 253 | * The draft can be modified until you finalize it with the `finishDraft` function.
|
|---|
| 254 | */
|
|---|
| 255 | declare const createDraft: <T extends Objectish>(base: T) => Draft<T>;
|
|---|
| 256 | /**
|
|---|
| 257 | * Finalize an Immer draft from a `createDraft` call, returning the base state
|
|---|
| 258 | * (if no changes were made) or a modified copy. The draft must *not* be
|
|---|
| 259 | * mutated afterwards.
|
|---|
| 260 | *
|
|---|
| 261 | * Pass a function as the 2nd argument to generate Immer patches based on the
|
|---|
| 262 | * changes that were made.
|
|---|
| 263 | */
|
|---|
| 264 | declare const finishDraft: <D extends unknown>(draft: D, patchListener?: PatchListener | undefined) => D extends Draft<infer T> ? T : never;
|
|---|
| 265 | /**
|
|---|
| 266 | * This function is actually a no-op, but can be used to cast an immutable type
|
|---|
| 267 | * to an draft type and make TypeScript happy
|
|---|
| 268 | *
|
|---|
| 269 | * @param value
|
|---|
| 270 | */
|
|---|
| 271 | declare function castDraft<T>(value: T): Draft<T>;
|
|---|
| 272 | /**
|
|---|
| 273 | * This function is actually a no-op, but can be used to cast a mutable type
|
|---|
| 274 | * to an immutable type and make TypeScript happy
|
|---|
| 275 | * @param value
|
|---|
| 276 | */
|
|---|
| 277 | declare function castImmutable<T>(value: T): Immutable<T>;
|
|---|
| 278 |
|
|---|
| 279 | export { Draft, Immer, Immutable, Objectish, Patch, PatchListener, Producer, StrictMode, WritableDraft, applyPatches, castDraft, castImmutable, createDraft, current, enableMapSet, enablePatches, finishDraft, freeze, DRAFTABLE as immerable, isDraft, isDraftable, NOTHING as nothing, original, produce, produceWithPatches, setAutoFreeze, setUseStrictIteration, setUseStrictShallowCopy };
|
|---|