or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-utilities.mdcore-production.mddraft-management.mdindex.mdpatches-system.md
tile.json

core-production.mddocs/

0

# Core Production

1

2

The core production capabilities of Immer, centered around the `produce` function and its variants. These functions provide the main interface for creating immutable state through mutation-like syntax.

3

4

## Capabilities

5

6

### produce

7

8

The main function that takes a value and a "recipe function" to create immutable updates. The recipe function can mutate its first argument (a draft) and all mutations are applied to a copy of the base state.

9

10

```typescript { .api }

11

/**

12

* Creates immutable state by applying mutations to a draft of the base state

13

* @param base - The initial state to transform

14

* @param recipe - Function that receives a draft proxy for mutation

15

* @param patchListener - Optional listener for patch generation (requires enablePatches)

16

* @returns New immutable state or original state if no changes

17

*/

18

function produce<T>(

19

base: T,

20

recipe: (draft: Draft<T>) => void | T | undefined,

21

patchListener?: PatchListener

22

): T;

23

```

24

25

**Curried producer variant:**

26

27

```typescript { .api }

28

/**

29

* Creates a curried producer function

30

* @param recipe - Recipe function to apply to future base states

31

* @returns Function that accepts base state and returns transformed state

32

*/

33

function produce<T>(

34

recipe: (draft: Draft<T>) => void | T | undefined

35

): (base: T) => T;

36

```

37

38

**Curried producer with initial state:**

39

40

```typescript { .api }

41

/**

42

* Creates a curried producer with initial state

43

* @param recipe - Recipe function to apply

44

* @param initialState - Default state when none provided

45

* @returns Function that optionally accepts base state

46

*/

47

function produce<T>(

48

recipe: (draft: Draft<T>) => void | T | undefined,

49

initialState: T

50

): (base?: T) => T;

51

```

52

53

**Usage Examples:**

54

55

```typescript

56

import { produce } from "immer";

57

58

// Basic usage

59

const baseState = { count: 0, items: [1, 2, 3] };

60

61

const nextState = produce(baseState, draft => {

62

draft.count += 1;

63

draft.items.push(4);

64

});

65

66

// Curried producer

67

const increment = produce((draft: { count: number }) => {

68

draft.count += 1;

69

});

70

71

const result1 = increment({ count: 5 }); // { count: 6 }

72

const result2 = increment({ count: 10 }); // { count: 11 }

73

74

// Returning a value from recipe (replaces entire state)

75

const replaced = produce(baseState, draft => {

76

return { count: 100, items: [10, 20] };

77

});

78

79

// Conditional updates

80

const conditionalUpdate = produce(baseState, draft => {

81

if (draft.count < 10) {

82

draft.count *= 2;

83

}

84

});

85

86

// Working with arrays

87

const todos = [

88

{ id: 1, text: "Learn Immer", done: false },

89

{ id: 2, text: "Use Immer", done: false }

90

];

91

92

const updatedTodos = produce(todos, draft => {

93

const todo = draft.find(t => t.id === 1);

94

if (todo) {

95

todo.done = true;

96

}

97

draft.push({ id: 3, text: "Master Immer", done: false });

98

});

99

```

100

101

### produceWithPatches

102

103

Like `produce`, but always returns a tuple containing the next state, patches describing the changes, and inverse patches for reverting the changes.

104

105

```typescript { .api }

106

/**

107

* Produces next state with patch information for change tracking

108

* @param base - The initial state to transform

109

* @param recipe - Function that receives a draft proxy for mutation

110

* @returns Tuple of [nextState, patches, inversePatches]

111

*/

112

function produceWithPatches<T>(

113

base: T,

114

recipe: (draft: Draft<T>) => void | T | undefined

115

): [T, Patch[], Patch[]];

116

```

117

118

**Requirements:** Must call `enablePatches()` before using this function.

119

120

**Usage Examples:**

121

122

```typescript

123

import { produceWithPatches, enablePatches, applyPatches } from "immer";

124

125

// Enable patches functionality

126

enablePatches();

127

128

const baseState = {

129

user: { name: "John", age: 30 },

130

todos: ["Learn Immer"]

131

};

132

133

const [nextState, patches, inversePatches] = produceWithPatches(baseState, draft => {

134

draft.user.age = 31;

135

draft.todos.push("Use Immer in project");

136

});

137

138

console.log(patches);

139

// [

140

// { op: "replace", path: ["user", "age"], value: 31 },

141

// { op: "add", path: ["todos", 1], value: "Use Immer in project" }

142

// ]

143

144

console.log(inversePatches);

145

// [

146

// { op: "replace", path: ["user", "age"], value: 30 },

147

// { op: "remove", path: ["todos", 1] }

148

// ]

149

150

// Apply patches to recreate the change

151

const recreated = applyPatches(baseState, patches);

152

console.log(recreated === nextState); // false (different objects)

153

console.log(JSON.stringify(recreated) === JSON.stringify(nextState)); // true (same content)

154

155

// Revert changes using inverse patches

156

const reverted = applyPatches(nextState, inversePatches);

157

console.log(JSON.stringify(reverted) === JSON.stringify(baseState)); // true

158

```

159

160

### Return Value Semantics

161

162

Producer functions support several return patterns:

163

164

```typescript

165

import { produce, nothing } from "immer";

166

167

const state = { items: [1, 2, 3], meta: { count: 3 } };

168

169

// Return undefined (default) - apply draft mutations

170

const result1 = produce(state, draft => {

171

draft.items.push(4);

172

draft.meta.count += 1;

173

// implicit return undefined

174

});

175

176

// Return the draft - apply draft mutations

177

const result2 = produce(state, draft => {

178

draft.items.push(5);

179

return draft; // same as returning undefined

180

});

181

182

// Return a completely new object - replace entire state

183

const result3 = produce(state, draft => {

184

return { items: [10, 20], meta: { count: 2 } };

185

});

186

187

// Return nothing symbol - replace state with undefined

188

const result4 = produce(state, draft => {

189

return nothing;

190

}); // result4 is undefined

191

192

// Conditional replacement

193

const result5 = produce(state, draft => {

194

if (draft.items.length > 5) {

195

return { items: [], meta: { count: 0 } }; // reset

196

}

197

draft.items.push(6); // mutation

198

});

199

```

200

201

## Type Safety

202

203

```typescript { .api }

204

interface IProduce {

205

// Base + recipe + optional patchListener

206

<T = any>(

207

base: T,

208

recipe: (draft: Draft<T>) => void | T | undefined,

209

listener?: PatchListener

210

): T;

211

212

// Curried producer

213

<T = any>(

214

recipe: (draft: Draft<T>) => void | T | undefined

215

): (base: T) => T;

216

217

// Curried producer with initial state

218

<T = any>(

219

recipe: (draft: Draft<T>) => void | T | undefined,

220

initialState: T

221

): (base?: T) => T;

222

}

223

224

interface IProduceWithPatches {

225

<T = any>(

226

base: T,

227

recipe: (draft: Draft<T>) => void | T | undefined

228

): [T, Patch[], Patch[]];

229

}

230

```

231

232

The core production functions provide the foundation for all immutable state updates in Immer, with full TypeScript support and flexible usage patterns for different scenarios.