+import { value } from '../src/value'
+import { effect, observable } from '../src/index'
+
+describe('observer/value', () => {
+ it('should hold a value', () => {
+ const a = value(1)
+ expect(a.value).toBe(1)
+ a.value = 2
+ expect(a.value).toBe(2)
+ })
+
+ it('should be reactive', () => {
+ const a = value(1)
+ let dummy
+ effect(() => {
+ dummy = a.value
+ })
+ expect(dummy).toBe(1)
+ a.value = 2
+ expect(dummy).toBe(2)
+ })
+
+ it('should make nested properties reactive', () => {
+ const a = value({
+ count: 1
+ })
+ let dummy
+ effect(() => {
+ dummy = a.value.count
+ })
+ expect(dummy).toBe(1)
+ a.value.count = 2
+ expect(dummy).toBe(2)
+ })
+
+ it('should work like a normal property when nested in an observable', () => {
+ const a = value(1)
+ const obj = observable({
+ a,
+ b: {
+ c: a
+ }
+ })
+ let dummy
+ effect(() => {
+ dummy = obj.a
+ })
+ expect(dummy).toBe(1)
+ a.value++
+ expect(dummy).toBe(2)
+ obj.a++
+ expect(dummy).toBe(3)
+ })
+})
DebuggerEvent
} from './effect'
+import { UnwrapBindings } from './value'
+
export { ReactiveEffect, ReactiveEffectOptions, DebuggerEvent }
export { OperationTypes } from './operations'
export { computed, ComputedValue } from './computed'
export { lock, unlock } from './lock'
-export { value, isValue, Value } from './value'
+export { value, isValue, Value, UnwrapBindings } from './value'
const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
)
}
-type identity = <T>(target?: T) => T
+type ObservableFactory = <T>(target?: T) => UnwrapBindings<T>
export const observable = ((target: any = {}): any => {
// if trying to observe an immutable proxy, return the immutable version.
mutableHandlers,
mutableCollectionHandlers
)
-}) as identity
+}) as ObservableFactory
export const immutable = ((target: any = {}): any => {
// value is a mutable observable, retrive its original and return
immutableHandlers,
immutableCollectionHandlers
)
-}) as identity
+}) as ObservableFactory
function createObservable(
target: any,
value: T
}
+type UnwrapValue<T, U = T> = T extends Value<infer V> ? V : T extends {} ? U : T
+
+// A utility type that recursively unwraps value bindings nested inside an
+// observable object. Unfortunately TS cannot do recursive types, but this
+// should be enough for practical use cases...
+export type UnwrapBindings<T> = {
+ [key in keyof T]: UnwrapValue<
+ T[key],
+ {
+ [k2 in keyof T[key]]: UnwrapValue<
+ T[key][k2],
+ {
+ [k3 in keyof T[key][k2]]: UnwrapValue<
+ T[key][k2][k3],
+ {
+ [k4 in keyof T[key][k2][k3]]: UnwrapValue<
+ T[key][k2][k3][k4],
+ {
+ [k5 in keyof T[key][k2][k3][k4]]: UnwrapValue<
+ T[key][k2][k3][k4][k5],
+ {
+ [k6 in keyof T[key][k2][k3][k4][k5]]: UnwrapValue<
+ T[key][k2][k3][k4][k5][k6],
+ {
+ [k7 in keyof T[key][k2][k3][k4][k5][k6]]: UnwrapValue<
+ T[key][k2][k3][k4][k5][k6][k7],
+ {
+ [k8 in keyof T[key][k2][k3][k4][k5][k6][k7]]: UnwrapValue<
+ T[key][k2][k3][k4][k5][k6][k7][k8],
+ {
+ [k9 in keyof T[key][k2][k3][k4][k5][k6][k7][k8]]: UnwrapValue<
+ T[key][k2][k3][k4][k5][k6][k7][k8][k9],
+ {
+ [k10 in keyof T[key][k2][k3][k4][k5][k6][k7][k8][k9]]: UnwrapValue<
+ T[key][k2][k3][k4][k5][k6][k7][k8][k9][k10]
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+ }
+ >
+}
+
const convert = (val: any): any => (isObject(val) ? observable(val) : val)
export function value<T>(raw: T): Value<T> {
import { VNode, normalizeVNode, VNodeChild } from './vnode'
-import { ReactiveEffect, observable } from '@vue/observer'
+import { ReactiveEffect, UnwrapBindings, observable } from '@vue/observer'
import { isFunction, EMPTY_OBJ } from '@vue/shared'
import { RenderProxyHandlers } from './componentProxy'
import { ComponentPropsOptions, PropValidator } from './componentProps'
-interface Value<T> {
- value: T
-}
-
export type Data = { [key: string]: any }
-type UnwrapBindings<T> = {
- [key in keyof T]: T[key] extends Value<infer V> ? V : T[key]
-}
-
type ExtractPropTypes<PropOptions> = {
readonly [key in keyof PropOptions]: PropOptions[key] extends PropValidator<
infer V