Skip to content

Commit

Permalink
feat(reactivity): support default value in toRef()
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 11, 2021
1 parent d0ea900 commit 2db9c90
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
12 changes: 12 additions & 0 deletions packages/reactivity/__tests__/ref.spec.ts
Expand Up @@ -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,
Expand Down
25 changes: 22 additions & 3 deletions packages/reactivity/src/ref.ts
Expand Up @@ -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) {
Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions test-dts/ref.test-d.ts
Expand Up @@ -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'
Expand Down

0 comments on commit 2db9c90

Please sign in to comment.