]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(reactivity): support default value in toRef()
authorEvan You <yyx990803@gmail.com>
Sat, 11 Dec 2021 08:41:58 +0000 (16:41 +0800)
committerEvan You <yyx990803@gmail.com>
Sat, 11 Dec 2021 08:41:58 +0000 (16:41 +0800)
packages/reactivity/__tests__/ref.spec.ts
packages/reactivity/src/ref.ts
test-dts/ref.test-d.ts

index 0abe05ce928577704f76a854952db0596638b212..0db801a5a429b2915b63296f8512065f9ee71b79 100644 (file)
@@ -269,6 +269,18 @@ describe('reactivity/ref', () => {
     expect(toRef(r, 'x')).toBe(r.x)
   })
 
+  test('toRef default value', () => {
+    const a: { x: number | undefined } = { x: undefined }
+    const x = toRef(a, 'x', 1)
+    expect(x.value).toBe(1)
+
+    a.x = 2
+    expect(x.value).toBe(2)
+
+    a.x = undefined
+    expect(x.value).toBe(1)
+  })
+
   test('toRefs', () => {
     const a = reactive({
       x: 1,
index 3e00541c743f3b62e582a6bc27804d8a85e2e983..66c3dd439828563ace870f5e02721d16c797042c 100644 (file)
@@ -206,10 +206,15 @@ export function toRefs<T extends object>(object: T): ToRefs<T> {
 class ObjectRefImpl<T extends object, K extends keyof T> {
   public readonly __v_isRef = true
 
-  constructor(private readonly _object: T, private readonly _key: K) {}
+  constructor(
+    private readonly _object: T,
+    private readonly _key: K,
+    private readonly _defaultValue?: T[K]
+  ) {}
 
   get value() {
-    return this._object[this._key]
+    const val = this._object[this._key]
+    return val === undefined ? (this._defaultValue as T[K]) : val
   }
 
   set value(newVal) {
@@ -222,9 +227,23 @@ export type ToRef<T> = [T] extends [Ref] ? T : Ref<T>
 export function toRef<T extends object, K extends keyof T>(
   object: T,
   key: K
+): ToRef<T[K]>
+
+export function toRef<T extends object, K extends keyof T>(
+  object: T,
+  key: K,
+  defaultValue: T[K]
+): ToRef<Exclude<T[K], undefined>>
+
+export function toRef<T extends object, K extends keyof T>(
+  object: T,
+  key: K,
+  defaultValue?: T[K]
 ): ToRef<T[K]> {
   const val = object[key]
-  return isRef(val) ? val : (new ObjectRefImpl(object, key) as any)
+  return isRef(val)
+    ? val
+    : (new ObjectRefImpl(object, key, defaultValue) as any)
 }
 
 // corner case when use narrows type
index 5b5274c98813435307769bab5b8ffdac03a60085..f91d6415f70f7d3bc5a256bd402f89cea381da6a 100644 (file)
@@ -224,6 +224,13 @@ expectType<Ref<string>>(p2.obj.k)
   expectType<Ref<number>>(toRefsResult.a.value.b)
 }
 
+// toRef default value
+{
+  const obj: { x?: number } = {}
+  const x = toRef(obj, 'x', 1)
+  expectType<Ref<number>>(x)
+}
+
 // #2687
 interface AppData {
   state: 'state1' | 'state2' | 'state3'