]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: improve computed typing + test for setters
authorEvan You <yyx990803@gmail.com>
Wed, 21 Aug 2019 16:01:05 +0000 (12:01 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 21 Aug 2019 16:01:05 +0000 (12:01 -0400)
packages/reactivity/__tests__/computed.spec.ts
packages/reactivity/__tests__/immutable.spec.ts
packages/reactivity/__tests__/ref.spec.ts
packages/reactivity/src/computed.ts
packages/reactivity/src/reactive.ts
packages/runtime-core/src/apiReactivity.ts

index 585f7abb33950fec356a4878d345a3c81cd2b0ef..898f9cac20ed4bff35ab84f468426492b6be2dc4 100644 (file)
@@ -1,4 +1,4 @@
-import { computed, reactive, effect, stop } from '../src'
+import { computed, reactive, effect, stop, ref } from '../src'
 
 describe('reactivity/computed', () => {
   it('should return updated value', () => {
@@ -123,6 +123,38 @@ describe('reactivity/computed', () => {
   })
 
   it('should support setter', () => {
-    // TODO
+    const n = ref(1)
+    const plusOne = computed({
+      get: () => n.value + 1,
+      set: val => {
+        n.value = val - 1
+      }
+    })
+
+    expect(plusOne.value).toBe(2)
+    n.value++
+    expect(plusOne.value).toBe(3)
+
+    plusOne.value = 0
+    expect(n.value).toBe(-1)
+  })
+
+  it('should trigger effect w/ setter', () => {
+    const n = ref(1)
+    const plusOne = computed({
+      get: () => n.value + 1,
+      set: val => {
+        n.value = val - 1
+      }
+    })
+
+    let dummy
+    effect(() => {
+      dummy = n.value
+    })
+    expect(dummy).toBe(1)
+
+    plusOne.value = 0
+    expect(dummy).toBe(-1)
   })
 })
index 83d4de7547af41c0ce5433bae8944ad0c44af88c..49b2fa57f4be9563b2ac48d157b4e0745828cc60 100644 (file)
@@ -45,7 +45,7 @@ describe('reactivity/immutable', () => {
     })
 
     it('should not allow mutation', () => {
-      const observed = immutable({ foo: 1, bar: { baz: 2 } })
+      const observed: any = immutable({ foo: 1, bar: { baz: 2 } })
       observed.foo = 2
       expect(observed.foo).toBe(1)
       expect(warn).toHaveBeenCalledTimes(1)
@@ -76,7 +76,7 @@ describe('reactivity/immutable', () => {
     })
 
     it('should not trigger effects when locked', () => {
-      const observed = immutable({ a: 1 })
+      const observed: any = immutable({ a: 1 })
       let dummy
       effect(() => {
         dummy = observed.a
@@ -88,7 +88,7 @@ describe('reactivity/immutable', () => {
     })
 
     it('should trigger effects when unlocked', () => {
-      const observed = immutable({ a: 1 })
+      const observed: any = immutable({ a: 1 })
       let dummy
       effect(() => {
         dummy = observed.a
@@ -146,7 +146,7 @@ describe('reactivity/immutable', () => {
     })
 
     it('should allow mutation when unlocked', () => {
-      const observed: any[] = immutable([{ foo: 1, bar: { baz: 2 } }])
+      const observed: any = immutable([{ foo: 1, bar: { baz: 2 } }])
       unlock()
       observed[1] = 2
       observed.push(3)
@@ -162,7 +162,7 @@ describe('reactivity/immutable', () => {
     })
 
     it('should not trigger effects when locked', () => {
-      const observed = immutable([{ a: 1 }])
+      const observed: any = immutable([{ a: 1 }])
       let dummy
       effect(() => {
         dummy = observed[0].a
@@ -177,7 +177,7 @@ describe('reactivity/immutable', () => {
     })
 
     it('should trigger effects when unlocked', () => {
-      const observed = immutable([{ a: 1 }])
+      const observed: any = immutable([{ a: 1 }])
       let dummy
       effect(() => {
         dummy = observed[0].a
@@ -256,7 +256,7 @@ describe('reactivity/immutable', () => {
           const key1 = {}
           const key2 = {}
           const original = new Collection([[key1, {}], [key2, {}]])
-          const observed = immutable(original)
+          const observed: any = immutable(original)
           for (const [key, value] of observed) {
             expect(isImmutable(key)).toBe(true)
             expect(isImmutable(value)).toBe(true)
@@ -322,7 +322,7 @@ describe('reactivity/immutable', () => {
       if (Collection === Set) {
         test('should retrive immutable values on iteration', () => {
           const original = new Collection([{}, {}])
-          const observed = immutable(original)
+          const observed: any = immutable(original)
           for (const value of observed) {
             expect(isImmutable(value)).toBe(true)
           }
index 2d26c933af53ad2770cefc69c76eef7ad01d2f3c..79730d6df6e2cf4bf2ee9a990172c66b3d4feb79 100644 (file)
@@ -32,7 +32,7 @@ describe('reactivity/value', () => {
     expect(dummy).toBe(2)
   })
 
-  it('should work like a normal property when nested in an observable', () => {
+  it('should work like a normal property when nested in a reactive object', () => {
     const a = ref(1)
     const obj = reactive({
       a,
index ef6e17c138d34ab5b5550fe28026e837b24a1413..5504ac79bbc57942de7a59f18de39fa8438bd590 100644 (file)
@@ -1,5 +1,5 @@
 import { effect, ReactiveEffect, activeReactiveEffectStack } from './effect'
-import { UnwrapNestedRefs, knownRefs } from './ref'
+import { UnwrapNestedRefs, knownRefs, Ref } from './ref'
 import { isFunction } from '@vue/shared'
 
 export interface ComputedRef<T> {
@@ -12,9 +12,11 @@ export interface ComputedOptions<T> {
   set: (v: T) => void
 }
 
+export function computed<T>(getter: () => T): ComputedRef<T>
+export function computed<T>(options: ComputedOptions<T>): Ref<T>
 export function computed<T>(
   getterOrOptions: (() => T) | ComputedOptions<T>
-): ComputedRef<T> {
+): Ref<T> {
   const isReadonly = isFunction(getterOrOptions)
   const getter = isReadonly
     ? (getterOrOptions as (() => T))
index c88ac28bd7933da11b40a8ac97714e4cf7671eb6..49b8fd382ecf7a336fb557894581424695bc71c6 100644 (file)
@@ -6,7 +6,7 @@ import {
   immutableCollectionHandlers
 } from './collectionHandlers'
 
-import { UnwrapRef } from './ref'
+import { UnwrapNestedRefs } from './ref'
 import { ReactiveEffect } from './effect'
 
 // The main WeakMap that stores {target -> key -> dep} connections.
@@ -40,9 +40,8 @@ const canObserve = (value: any): boolean => {
   )
 }
 
-type ObservableFactory = <T>(target?: T) => UnwrapRef<T>
-
-export const reactive = ((target: unknown): any => {
+export function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
+export function reactive(target: object) {
   // if trying to observe an immutable proxy, return the immutable version.
   if (immutableToRaw.has(target)) {
     return target
@@ -58,9 +57,12 @@ export const reactive = ((target: unknown): any => {
     mutableHandlers,
     mutableCollectionHandlers
   )
-}) as ObservableFactory
+}
 
-export const immutable = ((target: unknown): any => {
+export function immutable<T extends object>(
+  target: T
+): Readonly<UnwrapNestedRefs<T>>
+export function immutable(target: object) {
   // value is a mutable observable, retrive its original and return
   // a readonly version.
   if (observedToRaw.has(target)) {
@@ -73,7 +75,7 @@ export const immutable = ((target: unknown): any => {
     immutableHandlers,
     immutableCollectionHandlers
   )
-}) as ObservableFactory
+}
 
 function createReactiveObject(
   target: any,
index fa67f54cbbd8113b332c09c6f3017407075ffcdc..e8c69192bd3486b2f36818e1f7bdbdbcf612fcb9 100644 (file)
@@ -21,6 +21,7 @@ export {
 } from '@vue/reactivity'
 
 import {
+  Ref,
   computed as _computed,
   ComputedRef,
   ComputedOptions,
@@ -37,9 +38,9 @@ export function recordEffect(effect: ReactiveEffect) {
   }
 }
 
-export function computed<T>(
-  getterOrOptions: (() => T) | ComputedOptions<T>
-): ComputedRef<T> {
+export function computed<T>(getter: () => T): ComputedRef<T>
+export function computed<T>(options: ComputedOptions<T>): Ref<T>
+export function computed<T>(getterOrOptions: any) {
   const c = _computed(getterOrOptions)
   recordEffect(c.effect)
   return c