diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index e3633f982e0..ac3016d3e8c 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -21,7 +21,11 @@ export interface Ref { } export type ToRef = T extends Ref ? T : Ref> -export type ToRefs = { [K in keyof T]: ToRef } +export type ToRefs = { + // #2687: somehow using ToRef here turns the resulting type into + // a union of multiple Ref<*> types instead of a single Ref<* | *> type. + [K in keyof T]: T[K] extends Ref ? T[K] : Ref> +} const convert = (val: T): T => isObject(val) ? reactive(val) : val diff --git a/test-dts/ref.test-d.ts b/test-dts/ref.test-d.ts index f736977b5c8..83589f93c93 100644 --- a/test-dts/ref.test-d.ts +++ b/test-dts/ref.test-d.ts @@ -8,7 +8,8 @@ import { expectType, proxyRefs, toRef, - toRefs + toRefs, + ToRefs } from './index' function plainType(arg: number | Ref) { @@ -28,7 +29,6 @@ function plainType(arg: number | Ref) { const nestedRef = ref({ foo: ref(1) }) - expectType>(nestedRef) expectType<{ foo: number }>(nestedRef.value) // ref boolean @@ -171,3 +171,26 @@ expectType<{ a: Ref b: Ref }>(objRefs) + +// #2687 +interface AppData { + state: 'state1' | 'state2' | 'state3' +} + +const data: ToRefs = toRefs( + reactive({ + state: 'state1' + }) +) + +switch (data.state.value) { + case 'state1': + data.state.value = 'state2' + break + case 'state2': + data.state.value = 'state3' + break + case 'state3': + data.state.value = 'state1' + break +}