]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): fix ToRefs type on union value types
authorEvan You <yyx990803@gmail.com>
Wed, 2 Dec 2020 19:58:03 +0000 (14:58 -0500)
committerEvan You <yyx990803@gmail.com>
Wed, 2 Dec 2020 19:58:03 +0000 (14:58 -0500)
fix #2687

packages/reactivity/src/ref.ts
test-dts/ref.test-d.ts

index e3633f982e06b5576a86ebe2e1c414c563a10fd4..ac3016d3e8cd1bf2b67f8acf901d3546737736e4 100644 (file)
@@ -21,7 +21,11 @@ export interface Ref<T = any> {
 }
 
 export type ToRef<T> = T extends Ref ? T : Ref<UnwrapRef<T>>
-export type ToRefs<T = any> = { [K in keyof T]: ToRef<T[K]> }
+export type ToRefs<T = any> = {
+  // #2687: somehow using ToRef<T[K]> 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<UnwrapRef<T[K]>>
+}
 
 const convert = <T extends unknown>(val: T): T =>
   isObject(val) ? reactive(val) : val
index f736977b5c894729849594a0903b5dba6f56c6cb..83589f93c93316e27ba8acfa1be37e5b7665b247 100644 (file)
@@ -8,7 +8,8 @@ import {
   expectType,
   proxyRefs,
   toRef,
-  toRefs
+  toRefs,
+  ToRefs
 } from './index'
 
 function plainType(arg: number | Ref<number>) {
@@ -28,7 +29,6 @@ function plainType(arg: number | Ref<number>) {
   const nestedRef = ref({
     foo: ref(1)
   })
-  expectType<Ref<{ foo: number }>>(nestedRef)
   expectType<{ foo: number }>(nestedRef.value)
 
   // ref boolean
@@ -171,3 +171,26 @@ expectType<{
   a: Ref<number>
   b: Ref<number>
 }>(objRefs)
+
+// #2687
+interface AppData {
+  state: 'state1' | 'state2' | 'state3'
+}
+
+const data: ToRefs<AppData> = 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
+}