forked from mobxjs/mobx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathextendobservable.ts
More file actions
91 lines (87 loc) · 3.75 KB
/
Copy pathextendobservable.ts
File metadata and controls
91 lines (87 loc) · 3.75 KB
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
import { isObservableMap } from "../types/observablemap"
import { asObservableObject } from "../types/observableobject"
import { isObservable } from "./isobservable"
import { invariant, deprecated, fail } from "../utils/utils"
import { startBatch, endBatch } from "../core/observable"
import {
CreateObservableOptions,
asCreateObservableOptions,
shallowCreateObservableOptions,
deepDecorator,
refDecorator
} from "./observable"
import { isComputed } from "./iscomputed"
import { computedDecorator } from "./computed"
export function extendShallowObservable<A extends Object, B extends Object>(
target: A,
properties: B,
decorators?: { [K in keyof B]?: Function }
): A & B {
deprecated(
"'extendShallowObservable' is deprecated, use 'extendObservable(target, props, { deep: false })' instead"
)
return extendObservable(target, properties, decorators, shallowCreateObservableOptions)
}
export function extendObservable<A extends Object, B extends Object>(
target: A,
properties: B,
decorators?: { [K in keyof B]?: Function },
options?: CreateObservableOptions
): A & B {
if (process.env.NODE_ENV !== "production") {
invariant(
arguments.length >= 2 && arguments.length <= 4,
"'extendObservable' expected 2-4 arguments"
)
invariant(
typeof target === "object",
"'extendObservable' expects an object as first argument"
)
invariant(
!isObservableMap(target),
"'extendObservable' should not be used on maps, use map.merge instead"
)
invariant(
!isObservable(properties),
"Extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540"
)
if (decorators)
for (let key in decorators)
if (!(key in properties))
fail(`Trying to declare a decorator for unspecified property '${key}'`)
}
options = asCreateObservableOptions(options)
const defaultDecorator =
options.defaultDecorator || (options.deep === false ? refDecorator : deepDecorator)
asObservableObject(target, options.name, defaultDecorator.enhancer) // make sure object is observable, even without initial props
startBatch()
try {
for (let key in properties) {
const descriptor = Object.getOwnPropertyDescriptor(properties, key)!
if (process.env.NODE_ENV !== "production") {
if (Object.getOwnPropertyDescriptor(target, key))
fail(
`'extendObservable' can only be used to introduce new properties. Use 'set' or 'decorate' instead. The property '${key}' already exists on '${target}'`
)
if (isComputed(descriptor.value))
fail(
`Passing a 'computed' as initial property value is no longer supported by extendObservable. Use a getter or decorator instead`
)
}
const decorator =
decorators && key in decorators
? decorators[key]
: descriptor.get ? computedDecorator : defaultDecorator
if (process.env.NODE_ENV !== "production" && typeof decorator !== "function")
return fail(`Not a valid decorator for '${key}', got: ${decorator}`)
const resultDescriptor = decorator!(target, key, descriptor, true)
if (
resultDescriptor // otherwise, assume already applied, due to `applyToInstance`
)
Object.defineProperty(target, key, resultDescriptor)
}
} finally {
endBatch()
}
return target as any
}