fix(types): fix ref unwrapping type inference for nested shallowReactive & shallowRef
fix #4771
This commit is contained in:
		
							parent
							
								
									e772108922
								
							
						
					
					
						commit
						20a361541c
					
				@ -27,6 +27,7 @@ export {
 | 
				
			|||||||
  toRaw,
 | 
					  toRaw,
 | 
				
			||||||
  ReactiveFlags,
 | 
					  ReactiveFlags,
 | 
				
			||||||
  DeepReadonly,
 | 
					  DeepReadonly,
 | 
				
			||||||
 | 
					  ShallowReactive,
 | 
				
			||||||
  UnwrapNestedRefs
 | 
					  UnwrapNestedRefs
 | 
				
			||||||
} from './reactive'
 | 
					} from './reactive'
 | 
				
			||||||
export {
 | 
					export {
 | 
				
			||||||
 | 
				
			|||||||
@ -99,12 +99,18 @@ export function reactive(target: object) {
 | 
				
			|||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export declare const ShallowReactiveMarker: unique symbol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type ShallowReactive<T> = T & { [ShallowReactiveMarker]?: true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Return a shallowly-reactive copy of the original object, where only the root
 | 
					 * Return a shallowly-reactive copy of the original object, where only the root
 | 
				
			||||||
 * level properties are reactive. It also does not auto-unwrap refs (even at the
 | 
					 * level properties are reactive. It also does not auto-unwrap refs (even at the
 | 
				
			||||||
 * root level).
 | 
					 * root level).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export function shallowReactive<T extends object>(target: T): T {
 | 
					export function shallowReactive<T extends object>(
 | 
				
			||||||
 | 
					  target: T
 | 
				
			||||||
 | 
					): ShallowReactive<T> {
 | 
				
			||||||
  return createReactiveObject(
 | 
					  return createReactiveObject(
 | 
				
			||||||
    target,
 | 
					    target,
 | 
				
			||||||
    false,
 | 
					    false,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,13 @@
 | 
				
			|||||||
import { isTracking, trackEffects, triggerEffects } from './effect'
 | 
					import { isTracking, trackEffects, triggerEffects } from './effect'
 | 
				
			||||||
import { TrackOpTypes, TriggerOpTypes } from './operations'
 | 
					import { TrackOpTypes, TriggerOpTypes } from './operations'
 | 
				
			||||||
import { isArray, hasChanged } from '@vue/shared'
 | 
					import { isArray, hasChanged } from '@vue/shared'
 | 
				
			||||||
import { isProxy, toRaw, isReactive, toReactive } from './reactive'
 | 
					import {
 | 
				
			||||||
 | 
					  isProxy,
 | 
				
			||||||
 | 
					  toRaw,
 | 
				
			||||||
 | 
					  isReactive,
 | 
				
			||||||
 | 
					  toReactive,
 | 
				
			||||||
 | 
					  ShallowReactiveMarker
 | 
				
			||||||
 | 
					} from './reactive'
 | 
				
			||||||
import { CollectionTypes } from './collectionHandlers'
 | 
					import { CollectionTypes } from './collectionHandlers'
 | 
				
			||||||
import { createDep, Dep } from './dep'
 | 
					import { createDep, Dep } from './dep'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -74,11 +80,15 @@ export function ref(value?: unknown) {
 | 
				
			|||||||
  return createRef(value, false)
 | 
					  return createRef(value, false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare const ShallowRefMarker: unique symbol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ShallowRef<T = any> = Ref<T> & { [ShallowRefMarker]?: true }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function shallowRef<T extends object>(
 | 
					export function shallowRef<T extends object>(
 | 
				
			||||||
  value: T
 | 
					  value: T
 | 
				
			||||||
): T extends Ref ? T : Ref<T>
 | 
					): T extends Ref ? T : ShallowRef<T>
 | 
				
			||||||
export function shallowRef<T>(value: T): Ref<T>
 | 
					export function shallowRef<T>(value: T): ShallowRef<T>
 | 
				
			||||||
export function shallowRef<T = any>(): Ref<T | undefined>
 | 
					export function shallowRef<T = any>(): ShallowRef<T | undefined>
 | 
				
			||||||
export function shallowRef(value?: unknown) {
 | 
					export function shallowRef(value?: unknown) {
 | 
				
			||||||
  return createRef(value, true)
 | 
					  return createRef(value, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -215,6 +225,7 @@ class ObjectRefImpl<T extends object, K extends keyof T> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ToRef<T> = [T] extends [Ref] ? T : Ref<T>
 | 
					export type ToRef<T> = [T] extends [Ref] ? T : Ref<T>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function toRef<T extends object, K extends keyof T>(
 | 
					export function toRef<T extends object, K extends keyof T>(
 | 
				
			||||||
  object: T,
 | 
					  object: T,
 | 
				
			||||||
  key: K
 | 
					  key: K
 | 
				
			||||||
@ -258,7 +269,9 @@ export type ShallowUnwrapRef<T> = {
 | 
				
			|||||||
    : T[K]
 | 
					    : T[K]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type UnwrapRef<T> = T extends Ref<infer V>
 | 
					export type UnwrapRef<T> = T extends ShallowRef<infer V>
 | 
				
			||||||
 | 
					  ? V
 | 
				
			||||||
 | 
					  : T extends Ref<infer V>
 | 
				
			||||||
  ? UnwrapRefSimple<V>
 | 
					  ? UnwrapRefSimple<V>
 | 
				
			||||||
  : UnwrapRefSimple<T>
 | 
					  : UnwrapRefSimple<T>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -271,7 +284,7 @@ export type UnwrapRefSimple<T> = T extends
 | 
				
			|||||||
  ? T
 | 
					  ? T
 | 
				
			||||||
  : T extends Array<any>
 | 
					  : T extends Array<any>
 | 
				
			||||||
  ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
 | 
					  ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
 | 
				
			||||||
  : T extends object
 | 
					  : T extends object & { [ShallowReactiveMarker]?: never }
 | 
				
			||||||
  ? {
 | 
					  ? {
 | 
				
			||||||
      [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
 | 
					      [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -161,7 +161,8 @@ export {
 | 
				
			|||||||
  UnwrapRef,
 | 
					  UnwrapRef,
 | 
				
			||||||
  ShallowUnwrapRef,
 | 
					  ShallowUnwrapRef,
 | 
				
			||||||
  WritableComputedOptions,
 | 
					  WritableComputedOptions,
 | 
				
			||||||
  DeepReadonly
 | 
					  DeepReadonly,
 | 
				
			||||||
 | 
					  ShallowReactive
 | 
				
			||||||
} from '@vue/reactivity'
 | 
					} from '@vue/reactivity'
 | 
				
			||||||
export {
 | 
					export {
 | 
				
			||||||
  WatchEffect,
 | 
					  WatchEffect,
 | 
				
			||||||
 | 
				
			|||||||
@ -239,13 +239,65 @@ function testUnrefGenerics<T>(p: T | Ref<T>) {
 | 
				
			|||||||
testUnrefGenerics(1)
 | 
					testUnrefGenerics(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// #4732
 | 
					// #4732
 | 
				
			||||||
const baz = shallowReactive({
 | 
					describe('ref in shallow reactive', () => {
 | 
				
			||||||
  foo: {
 | 
					  const baz = shallowReactive({
 | 
				
			||||||
    bar: ref(42)
 | 
					    foo: {
 | 
				
			||||||
  }
 | 
					      bar: ref(42)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const foo = toRef(baz, 'foo')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  expectType<Ref<number>>(foo.value.bar)
 | 
				
			||||||
 | 
					  expectType<number>(foo.value.bar.value)
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const foo = toRef(baz, 'foo')
 | 
					// #4771
 | 
				
			||||||
 | 
					describe('shallow reactive in reactive', () => {
 | 
				
			||||||
 | 
					  const baz = reactive({
 | 
				
			||||||
 | 
					    foo: shallowReactive({
 | 
				
			||||||
 | 
					      a: {
 | 
				
			||||||
 | 
					        b: ref(42)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
expectType<Ref<number>>(foo.value.bar)
 | 
					  const foo = toRef(baz, 'foo')
 | 
				
			||||||
expectType<number>(foo.value.bar.value)
 | 
					
 | 
				
			||||||
 | 
					  expectType<Ref<number>>(foo.value.a.b)
 | 
				
			||||||
 | 
					  expectType<number>(foo.value.a.b.value)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('shallow ref in reactive', () => {
 | 
				
			||||||
 | 
					  const x = reactive({
 | 
				
			||||||
 | 
					    foo: shallowRef({
 | 
				
			||||||
 | 
					      bar: {
 | 
				
			||||||
 | 
					        baz: ref(123),
 | 
				
			||||||
 | 
					        qux: reactive({
 | 
				
			||||||
 | 
					          z: ref(123)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  expectType<Ref<number>>(x.foo.bar.baz)
 | 
				
			||||||
 | 
					  expectType<number>(x.foo.bar.qux.z)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('ref in shallow ref', () => {
 | 
				
			||||||
 | 
					  const x = shallowRef({
 | 
				
			||||||
 | 
					    a: ref(123)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  expectType<Ref<number>>(x.value.a)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('reactive in shallow ref', () => {
 | 
				
			||||||
 | 
					  const x = shallowRef({
 | 
				
			||||||
 | 
					    a: reactive({
 | 
				
			||||||
 | 
					      b: ref(0)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  expectType<number>(x.value.a.b)
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user