Skip to content

Commit e315d84

Browse files
committed
fix(types): fix ToRefs type on union value types
fix #2687
1 parent 24a7a2d commit e315d84

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

packages/reactivity/src/ref.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ export interface Ref<T = any> {
2121
}
2222

2323
export type ToRef<T> = T extends Ref ? T : Ref<UnwrapRef<T>>
24-
export type ToRefs<T = any> = { [K in keyof T]: ToRef<T[K]> }
24+
export type ToRefs<T = any> = {
25+
// #2687: somehow using ToRef<T[K]> here turns the resulting type into
26+
// a union of multiple Ref<*> types instead of a single Ref<* | *> type.
27+
[K in keyof T]: T[K] extends Ref ? T[K] : Ref<UnwrapRef<T[K]>>
28+
}
2529

2630
const convert = <T extends unknown>(val: T): T =>
2731
isObject(val) ? reactive(val) : val

test-dts/ref.test-d.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
expectType,
99
proxyRefs,
1010
toRef,
11-
toRefs
11+
toRefs,
12+
ToRefs
1213
} from './index'
1314

1415
function plainType(arg: number | Ref<number>) {
@@ -28,7 +29,6 @@ function plainType(arg: number | Ref<number>) {
2829
const nestedRef = ref({
2930
foo: ref(1)
3031
})
31-
expectType<Ref<{ foo: number }>>(nestedRef)
3232
expectType<{ foo: number }>(nestedRef.value)
3333

3434
// ref boolean
@@ -171,3 +171,26 @@ expectType<{
171171
a: Ref<number>
172172
b: Ref<number>
173173
}>(objRefs)
174+
175+
// #2687
176+
interface AppData {
177+
state: 'state1' | 'state2' | 'state3'
178+
}
179+
180+
const data: ToRefs<AppData> = toRefs(
181+
reactive({
182+
state: 'state1'
183+
})
184+
)
185+
186+
switch (data.state.value) {
187+
case 'state1':
188+
data.state.value = 'state2'
189+
break
190+
case 'state2':
191+
data.state.value = 'state3'
192+
break
193+
case 'state3':
194+
data.state.value = 'state1'
195+
break
196+
}

0 commit comments

Comments
 (0)