diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index 585f7abb..898f9cac 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -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) }) }) diff --git a/packages/reactivity/__tests__/immutable.spec.ts b/packages/reactivity/__tests__/immutable.spec.ts index 83d4de75..49b2fa57 100644 --- a/packages/reactivity/__tests__/immutable.spec.ts +++ b/packages/reactivity/__tests__/immutable.spec.ts @@ -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) } diff --git a/packages/reactivity/__tests__/ref.spec.ts b/packages/reactivity/__tests__/ref.spec.ts index 2d26c933..79730d6d 100644 --- a/packages/reactivity/__tests__/ref.spec.ts +++ b/packages/reactivity/__tests__/ref.spec.ts @@ -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, diff --git a/packages/reactivity/src/computed.ts b/packages/reactivity/src/computed.ts index ef6e17c1..5504ac79 100644 --- a/packages/reactivity/src/computed.ts +++ b/packages/reactivity/src/computed.ts @@ -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 { @@ -12,9 +12,11 @@ export interface ComputedOptions { set: (v: T) => void } +export function computed(getter: () => T): ComputedRef +export function computed(options: ComputedOptions): Ref export function computed( getterOrOptions: (() => T) | ComputedOptions -): ComputedRef { +): Ref { const isReadonly = isFunction(getterOrOptions) const getter = isReadonly ? (getterOrOptions as (() => T)) diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index c88ac28b..49b8fd38 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -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 = (target?: T) => UnwrapRef - -export const reactive = ((target: unknown): any => { +export function reactive(target: T): UnwrapNestedRefs +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( + target: T +): Readonly> +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, diff --git a/packages/runtime-core/src/apiReactivity.ts b/packages/runtime-core/src/apiReactivity.ts index fa67f54c..e8c69192 100644 --- a/packages/runtime-core/src/apiReactivity.ts +++ b/packages/runtime-core/src/apiReactivity.ts @@ -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( - getterOrOptions: (() => T) | ComputedOptions -): ComputedRef { +export function computed(getter: () => T): ComputedRef +export function computed(options: ComputedOptions): Ref +export function computed(getterOrOptions: any) { const c = _computed(getterOrOptions) recordEffect(c.effect) return c