test: test unwrapping computed refs

This commit is contained in:
Evan You 2019-10-14 11:21:09 -04:00
parent d8b2b9eb9c
commit 1c56d1bf19
3 changed files with 29 additions and 17 deletions

View File

@ -1,6 +1,7 @@
import { ref, isRef } from '../src/ref' import { ref, isRef } from '../src/ref'
import { reactive, isReactive, toRaw, markNonReactive } from '../src/reactive' import { reactive, isReactive, toRaw, markNonReactive } from '../src/reactive'
import { mockWarn } from '@vue/runtime-test' import { mockWarn } from '@vue/runtime-test'
import { computed } from '../src/computed'
describe('reactivity/reactive', () => { describe('reactivity/reactive', () => {
mockWarn() mockWarn()
@ -135,6 +136,22 @@ describe('reactivity/reactive', () => {
expect(isRef(observedObjectRef)).toBe(true) expect(isRef(observedObjectRef)).toBe(true)
}) })
test('should unwrap computed refs', () => {
// readonly
const a = computed(() => 1)
// writable
const b = computed({
get: () => 1,
set: () => {}
})
const obj = reactive({ a, b })
// check type
obj.a + 1
obj.b + 1
expect(typeof obj.a).toBe(`number`)
expect(typeof obj.b).toBe(`number`)
})
test('non-observable values', () => { test('non-observable values', () => {
const assertValue = (value: any) => { const assertValue = (value: any) => {
reactive(value) reactive(value)

View File

@ -1,13 +1,11 @@
import { isObject, toTypeString } from '@vue/shared' import { isObject, toTypeString } from '@vue/shared'
import { mutableHandlers, readonlyHandlers } from './baseHandlers' import { mutableHandlers, readonlyHandlers } from './baseHandlers'
import { import {
mutableCollectionHandlers, mutableCollectionHandlers,
readonlyCollectionHandlers readonlyCollectionHandlers
} from './collectionHandlers' } from './collectionHandlers'
import { UnwrapNestedRefs } from './ref'
import { ReactiveEffect } from './effect' import { ReactiveEffect } from './effect'
import { UnwrapRef, Ref } from './ref'
// The main WeakMap that stores {target -> key -> dep} connections. // The main WeakMap that stores {target -> key -> dep} connections.
// Conceptually, it's easier to think of a dependency as a Dep class // Conceptually, it's easier to think of a dependency as a Dep class
@ -40,6 +38,9 @@ const canObserve = (value: any): boolean => {
) )
} }
// only unwrap nested ref
type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRef<T>
export function reactive<T extends object>(target: T): UnwrapNestedRefs<T> export function reactive<T extends object>(target: T): UnwrapNestedRefs<T>
export function reactive(target: object) { export function reactive(target: object) {
// if trying to observe a readonly proxy, return the readonly version. // if trying to observe a readonly proxy, return the readonly version.

View File

@ -2,7 +2,7 @@ import { track, trigger } from './effect'
import { OperationTypes } from './operations' import { OperationTypes } from './operations'
import { isObject } from '@vue/shared' import { isObject } from '@vue/shared'
import { reactive } from './reactive' import { reactive } from './reactive'
import { ComputedRef, WritableComputedRef } from './computed' import { ComputedRef } from './computed'
export const refSymbol = Symbol(__DEV__ ? 'refSymbol' : '') export const refSymbol = Symbol(__DEV__ ? 'refSymbol' : '')
@ -73,22 +73,16 @@ type BailTypes =
// Recursively unwraps nested value bindings. // Recursively unwraps nested value bindings.
export type UnwrapRef<T> = { export type UnwrapRef<T> = {
cRef: T extends ComputedRef<infer V> ? UnwrapRef<V> : T cRef: T extends ComputedRef<infer V> ? UnwrapRef<V> : T
wcRef: T extends WritableComputedRef<infer V> ? UnwrapRef<V> : T
ref: T extends Ref<infer V> ? UnwrapRef<V> : T ref: T extends Ref<infer V> ? UnwrapRef<V> : T
array: T extends Array<infer V> ? Array<UnwrapRef<V>> : T array: T extends Array<infer V> ? Array<UnwrapRef<V>> : T
object: { [K in keyof T]: UnwrapRef<T[K]> } object: { [K in keyof T]: UnwrapRef<T[K]> }
stop: T stop: T
}[T extends ComputedRef<any> }[T extends ComputedRef<any>
? 'cRef' ? 'cRef'
: T extends WritableComputedRef<any> : T extends Ref
? 'wcRef' ? 'ref'
: T extends Ref : T extends Array<any>
? 'ref' ? 'array'
: T extends Array<any> : T extends BailTypes
? 'array' ? 'stop' // bail out on types that shouldn't be unwrapped
: T extends BailTypes : T extends object ? 'object' : 'stop']
? '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>