+import { ref, isRef } from '../src/ref'
import { reactive, isReactive, toRaw, markNonReactive } from '../src/reactive'
import { mockWarn } from '@vue/runtime-test'
expect(toRaw(original)).toBe(original)
})
+ test('should not unwrap Ref<T>', () => {
+ 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)
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)
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<T> extends WritableComputedRef<T> {
- readonly value: UnwrapNestedRefs<T>
+ readonly value: UnwrapRef<T>
}
export interface WritableComputedRef<T> extends Ref<T> {
export interface Ref<T = any> {
[refSymbol]: true
- value: UnwrapNestedRefs<T>
+ value: UnwrapRef<T>
}
-export type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRef<T>
-
const convert = (val: any): any => (isObject(val) ? reactive(val) : val)
export function ref<T>(raw: T): Ref<T> {
+ if (isRef(raw)) {
+ return raw
+ }
raw = convert(raw)
const v = {
[refSymbol]: true,
object: T,
key: K
): Ref<T[K]> {
- const v = {
+ return {
[refSymbol]: true,
- get value() {
+ get value(): any {
return object[key]
},
set value(newVal) {
object[key] = newVal
}
}
- return v as Ref<T[K]>
}
type BailTypes =
: 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> = T extends Ref ? T : UnwrapRef<T>