-
-
Notifications
You must be signed in to change notification settings - Fork 89
/
index.d.ts
executable file
·298 lines (250 loc) · 6.45 KB
/
index.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
export type Options = {
/**
Deep changes will not trigger the callback. Only changes to the immediate properties of the original object.
@default false
@example
```
import onChange from 'on-change';
const object = {
a: {
b: false
}
};
let index = 0;
const watchedObject = onChange(object, () => {
console.log('Object changed:', ++index);
}, {isShallow: true});
watchedObject.a.b = true;
// Nothing happens
watchedObject.a = true;
//=> 'Object changed: 1'
```
*/
readonly isShallow?: boolean;
/**
The function receives two arguments to be compared for equality. Should return `true` if the two values are determined to be equal.
@default Object.is
@example
```
import onChange from 'on-change';
const object = {
a: {
b: false
}
};
let index = 0;
const watchedObject = onChange(object, () => {
console.log('Object changed:', ++index);
}, {equals: (a, b) => a === b});
watchedObject.a.b = 0;
// Nothing happens
watchedObject.a = true;
//=> 'Object changed: 1'
```
*/
equals?: (a: unknown, b: unknown) => boolean;
/**
Setting properties as `Symbol` won't trigger the callback.
@default false
*/
readonly ignoreSymbols?: boolean;
/**
Setting properties in this array won't trigger the callback.
@default undefined
*/
readonly ignoreKeys?: ReadonlyArray<string | symbol>;
/**
Setting properties with an underscore as the first character won't trigger the callback.
@default false
*/
readonly ignoreUnderscores?: boolean;
/**
The path will be provided as an array of keys instead of a delimited string.
@default false
*/
readonly pathAsArray?: boolean;
/**
Ignore changes to objects that become detached from the watched object.
@default false
*/
readonly ignoreDetached?: boolean;
/**
Trigger callbacks for each change within specified method calls or all method calls.
@default false
*/
readonly details?: boolean | readonly string[];
/**
The function receives the same arguments and context as the [onChange callback](#onchange). The function is called whenever a change is attempted. Returning true will allow the change to be made and the onChange callback to execute, returning anything else will prevent the change from being made and the onChange callback will not trigger.
@example
```
import onChange from 'on-change';
const object = {a: 0};
let index = 0;
const watchedObject = onChange(object, () => {
console.log('Object changed:', ++index);
}, {onValidate: () => false});
watchedObject.a = true;
// watchedObject.a still equals 0
```
*/
onValidate?: (
this: unknown,
path: string,
value: unknown,
previousValue: unknown,
applyData: ApplyData
) => boolean;
};
export type ApplyData = {
/**
The name of the method that produced the change.
*/
readonly name: string;
/**
The arguments provided to the method that produced the change.
*/
readonly args: unknown[];
/**
The result returned from the method that produced the change.
*/
readonly result: unknown;
};
declare const onChange: {
/**
Watch an object or array for changes. It works recursively, so it will even detect if you modify a deep property like `obj.a.b[0].c = true`.
@param object - Object to watch for changes.
@param onChange - Function that gets called anytime the object changes.
@param [options] - Options for altering the behavior of onChange.
@returns A version of `object` that is watched. It's the exact same object, just with some `Proxy` traps.
@example
```
import onChange from 'on-change';
const object = {
foo: false,
a: {
b: [
{
c: false
}
]
}
};
let index = 0;
const watchedObject = onChange(object, function (path, value, previousValue, applyData) {
console.log('Object changed:', ++index);
console.log('this:', this);
console.log('path:', path);
console.log('value:', value);
console.log('previousValue:', previousValue);
console.log('applyData:', applyData);
});
watchedObject.foo = true;
//=> 'Object changed: 1'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: false
// }
// ]
// }
// }'
//=> 'path: "foo"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'applyData: undefined'
watchedObject.a.b[0].c = true;
//=> 'Object changed: 2'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: true
// }
// ]
// }
// }'
//=> 'path: "a.b.0.c"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'applyData: undefined'
watchedObject.a.b.push(3);
//=> 'Object changed: 3'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: true
// },
// 3
// ]
// }
// }'
//=> 'path: "a.b"'
//=> 'value: [{c: true}, 3]'
//=> 'previousValue: [{c: true}]'
//=> 'applyData: {
// name: "push",
// args: [3],
// result: 2,
// }'
// Access the original object
onChange.target(watchedObject).foo = false;
// Callback isn't called
// Unsubscribe
onChange.unsubscribe(watchedObject);
watchedObject.foo = 'bar';
// Callback isn't called
```
*/
<ObjectType extends Record<string, any>>(
object: ObjectType,
onChange: (
this: ObjectType,
path: string,
value: unknown,
previousValue: unknown,
applyData: ApplyData
) => void,
options?: Options & {pathAsArray?: false}
): ObjectType;
// Overload that returns a string array as path when `ignoreSymbols` and `pathAsArray` options are true.
<ObjectType extends Record<string, any>>(
object: ObjectType,
onChange: (
this: ObjectType,
path: string[],
value: unknown,
previousValue: unknown,
applyData: ApplyData
) => void,
options: Options & {ignoreSymbols: true; pathAsArray: true}
): ObjectType;
// Overload that returns an array as path when `pathAsArray` option is true.
<ObjectType extends Record<string, any>>(
object: ObjectType,
onChange: (
this: ObjectType,
path: Array<string | symbol>,
value: unknown,
previousValue: unknown,
applyData: ApplyData
) => void,
options: Options & {pathAsArray: true}
): ObjectType;
/**
@param object - Object that is already being watched for changes.
@returns The original unwatched object.
*/
target<ObjectType extends Record<string, any>>(object: ObjectType): ObjectType;
/**
Cancels all future callbacks on a watched object.
@param object - Object that is already being watched for changes.
@returns The original unwatched object.
*/
unsubscribe<ObjectType extends Record<string, any>>(object: ObjectType): ObjectType;
};
export default onChange;