diff --git a/packages/reactivity/__tests__/reactive.spec.ts b/packages/reactivity/__tests__/reactive.spec.ts index ebeac774..8743d78c 100644 --- a/packages/reactivity/__tests__/reactive.spec.ts +++ b/packages/reactivity/__tests__/reactive.spec.ts @@ -1,3 +1,4 @@ +import { ref, isRef } from '../src/ref' import { reactive, isReactive, toRaw, markNonReactive } from '../src/reactive' import { mockWarn } from '@vue/runtime-test' @@ -126,6 +127,14 @@ describe('reactivity/reactive', () => { expect(toRaw(original)).toBe(original) }) + test('should not unwrap Ref', () => { + const observedNumberRef = reactive(ref(1)) + const observedObjectRef = reactive(ref({ foo: 1 })) + + expect(isRef(observedNumberRef)).toBe(true) + expect(isRef(observedObjectRef)).toBe(true) + }) + test('non-observable values', () => { const assertValue = (value: any) => { reactive(value) diff --git a/packages/reactivity/__tests__/ref.spec.ts b/packages/reactivity/__tests__/ref.spec.ts index dd04ac6a..f2f02e10 100644 --- a/packages/reactivity/__tests__/ref.spec.ts +++ b/packages/reactivity/__tests__/ref.spec.ts @@ -63,6 +63,13 @@ describe('reactivity/ref', () => { expect(dummy3).toBe(3) }) + it('should unwrap nested ref in types', () => { + const a = ref(0) + const b = ref(a) + + expect(typeof (b.value + 1)).toBe('number') + }) + it('should unwrap nested values in types', () => { const a = { b: ref(0) diff --git a/packages/reactivity/src/computed.ts b/packages/reactivity/src/computed.ts index c1cf34cb..dcc1d4a4 100644 --- a/packages/reactivity/src/computed.ts +++ b/packages/reactivity/src/computed.ts @@ -1,9 +1,9 @@ import { effect, ReactiveEffect, activeReactiveEffectStack } from './effect' -import { Ref, refSymbol, UnwrapNestedRefs } from './ref' +import { Ref, refSymbol, UnwrapRef } from './ref' import { isFunction, NOOP } from '@vue/shared' export interface ComputedRef extends WritableComputedRef { - readonly value: UnwrapNestedRefs + readonly value: UnwrapRef } export interface WritableComputedRef extends Ref { diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 9e000d97..5aac9272 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -7,14 +7,15 @@ export const refSymbol = Symbol(__DEV__ ? 'refSymbol' : undefined) export interface Ref { [refSymbol]: true - value: UnwrapNestedRefs + value: UnwrapRef } -export type UnwrapNestedRefs = T extends Ref ? T : UnwrapRef - const convert = (val: any): any => (isObject(val) ? reactive(val) : val) export function ref(raw: T): Ref { + if (isRef(raw)) { + return raw + } raw = convert(raw) const v = { [refSymbol]: true, @@ -48,16 +49,15 @@ function toProxyRef( object: T, key: K ): Ref { - const v = { + return { [refSymbol]: true, - get value() { + get value(): any { return object[key] }, set value(newVal) { object[key] = newVal } } - return v as Ref } type BailTypes = @@ -80,3 +80,6 @@ export type UnwrapRef = { : T extends BailTypes ? 'stop' // bail out on types that shouldn't be unwrapped : T extends object ? 'object' : 'stop'] + +// only unwrap nested ref +export type UnwrapNestedRefs = T extends Ref ? T : UnwrapRef