Skip to content

Instantly share code, notes, and snippets.

@monsat
Last active April 6, 2023 11:48
Show Gist options
  • Save monsat/508ffc57eea34fdd0078b51a18a1016f to your computer and use it in GitHub Desktop.
Save monsat/508ffc57eea34fdd0078b51a18a1016f to your computer and use it in GitHub Desktop.
オブジェクトの各プロパティについて unref/ref する
import { describe, expect, it, test, vi } from 'vitest'
import {
unwrapRefs,
wrapRefs,
} from './unwrapRef'
describe('unwrapRefs', () => {
it('should be enabled to use Ref', () => {
const source = {
name: ref('John'),
age: ref(20),
}
const result = unwrapRefs(source)
expect(result.name).toBe('John')
expect(result.age).toBe(20)
})
it('should be enabled to use Ref', () => {
const source = {
name: 'John',
age: 20,
}
const result = unwrapRefs(source)
expect(result.name).toBe('John')
expect(result.age).toBe(20)
})
})
describe('wrapRefs', () => {
it('should be enabled to use Ref', () => {
const source = {
name: 'John',
age: 20,
}
const result = wrapRefs(source)
expect(result.name.value).toBe('John')
expect(result.age.value).toBe(20)
})
it('should be enabled to use Ref', () => {
const source = {
name: ref('John'),
age: ref(20),
}
const result = wrapRefs(source)
expect(result.name.value).toBe('John')
expect(result.age.value).toBe(20)
})
})
import { Ref, ref, unref } from 'vue'
export type UnwrapRef<T> = {
[K in keyof T]: T[K] extends Ref<infer U> ? U : T[K]
}
export type WrapRef<T> = {
[K in keyof T]: T[K] extends Ref<unknown> ? T[K] : Ref<T[K]>
}
/**
* オブジェクトの各プロパティについて Ref を解除する(unrefする)
* @param source unrefしたいオブジェクト
* @returns unrefしたオブジェクト
* @example
* const before = { name: Ref('John'), age: Ref(20) }
* const after = unwrapRefs(before) // { name: 'John', age: 20 }
*/
export const unwrapRefs = <T extends Record<string, unknown>>(source: T): UnwrapRef<T> => {
return Object.entries(source).reduce((accumulator, [key, value]) => {
accumulator[key as keyof T] = unref(value as Ref<any>) as UnwrapRef<T>[keyof T]
return accumulator
}, {} as UnwrapRef<T>)
}
/**
* オブジェクトの各プロパティについて Ref を作成する
* @param source refを作成したいオブジェクト
* @returns refを作成したオブジェクト
* @example
* const before = { name: 'John', age: 20 }
* const after = wrapRefs(before) // { name: Ref('John'), age: Ref(20) }
*/
export const wrapRefs = <T extends Record<string, unknown>>(source: T): WrapRef<T> => {
return Object.entries(source).reduce((accumulator, [key, value]) => {
accumulator[key as keyof T] = ref(value as T[keyof T]) as WrapRef<T>[keyof T]
return accumulator
}, {} as WrapRef<T>)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment