Skip to content

Commit 2db9c90

Browse files
committed
feat(reactivity): support default value in toRef()
1 parent d0ea900 commit 2db9c90

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

packages/reactivity/__tests__/ref.spec.ts

+12
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,18 @@ describe('reactivity/ref', () => {
269269
expect(toRef(r, 'x')).toBe(r.x)
270270
})
271271

272+
test('toRef default value', () => {
273+
const a: { x: number | undefined } = { x: undefined }
274+
const x = toRef(a, 'x', 1)
275+
expect(x.value).toBe(1)
276+
277+
a.x = 2
278+
expect(x.value).toBe(2)
279+
280+
a.x = undefined
281+
expect(x.value).toBe(1)
282+
})
283+
272284
test('toRefs', () => {
273285
const a = reactive({
274286
x: 1,

packages/reactivity/src/ref.ts

+22-3
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,15 @@ export function toRefs<T extends object>(object: T): ToRefs<T> {
206206
class ObjectRefImpl<T extends object, K extends keyof T> {
207207
public readonly __v_isRef = true
208208

209-
constructor(private readonly _object: T, private readonly _key: K) {}
209+
constructor(
210+
private readonly _object: T,
211+
private readonly _key: K,
212+
private readonly _defaultValue?: T[K]
213+
) {}
210214

211215
get value() {
212-
return this._object[this._key]
216+
const val = this._object[this._key]
217+
return val === undefined ? (this._defaultValue as T[K]) : val
213218
}
214219

215220
set value(newVal) {
@@ -222,9 +227,23 @@ export type ToRef<T> = [T] extends [Ref] ? T : Ref<T>
222227
export function toRef<T extends object, K extends keyof T>(
223228
object: T,
224229
key: K
230+
): ToRef<T[K]>
231+
232+
export function toRef<T extends object, K extends keyof T>(
233+
object: T,
234+
key: K,
235+
defaultValue: T[K]
236+
): ToRef<Exclude<T[K], undefined>>
237+
238+
export function toRef<T extends object, K extends keyof T>(
239+
object: T,
240+
key: K,
241+
defaultValue?: T[K]
225242
): ToRef<T[K]> {
226243
const val = object[key]
227-
return isRef(val) ? val : (new ObjectRefImpl(object, key) as any)
244+
return isRef(val)
245+
? val
246+
: (new ObjectRefImpl(object, key, defaultValue) as any)
228247
}
229248

230249
// corner case when use narrows type

test-dts/ref.test-d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ expectType<Ref<string>>(p2.obj.k)
224224
expectType<Ref<number>>(toRefsResult.a.value.b)
225225
}
226226

227+
// toRef default value
228+
{
229+
const obj: { x?: number } = {}
230+
const x = toRef(obj, 'x', 1)
231+
expectType<Ref<number>>(x)
232+
}
233+
227234
// #2687
228235
interface AppData {
229236
state: 'state1' | 'state2' | 'state3'

0 commit comments

Comments
 (0)