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