Subscribe on changes!

feature: ToRefInterface —— Wrap the attributes in the interface with Ref(将接口中的属性用Ref包裹)

avatar
Mar 7th 2023

What problem does this feature solve?

User requirements: In TypeScript, I have an interface, and I want to inherit the attributes of the interface after they are wrapped in Ref, so that the interface can be reused

用户需求:在TypeScript中,我有一个接口,我想将这个接口中的属性被Ref包裹后再进行继承,实现接口的复用

Specific scenario: I encapsulate the status and business logic that page rendering depends on into a file using provide/inject. I define an res interface for my network request API, the type of this res interface is exactly the same as that of the status, but it is not wrapped by Ref

具体场景:我将页面渲染所依赖的状态和业务逻辑使用provide/inject封装到了一个文件中,我为我的网络请求API定义了一个res interface,这个res interface的类型是与状态的类型完全一致的,只是没有被Ref包裹

What does the proposed API look like?

type ToRefInterface<OriginType> = {
  [Property in keyof OriginType]: Ref<OriginType[Property]>;
};

That's pretty much what I'd expect, but maybe you could do something more comprehensive, like let the user pass in generic parameters to determine which attributes in the interface will be wrapped by the Ref

简单实现了我所期望的功能,但或许可以做的更全面一些,比如说让用户自己传入泛型参数来决定接口中的哪些属性会被Ref包裹

Here is a concrete example:

下面是一个具体的使用例:

import { provide, inject, reactive, toRefs, Ref } from 'vue'
import { CommDeviceProfileRes } from '@/api/asset-analysis'

const commDeviceKey = Symbol('COMM_DEVICE')

type ToRefInterface<OriginType> = {
  [Property in keyof OriginType]: Ref<OriginType[Property]>
}

export interface CommDevice extends ToRefInterface<CommDeviceProfileRes> {
  // 增强先前定义的 res interface
  // enhance the 'res interface' 
  onAddQuickAccess: () => void
}

export function provideCommDevice(deviceId: string): CommDevice {
  const renderData: CommDeviceProfileRes = reactive({
    // res interface 中的属性,它们最终会被转成响应式返回
    // the attributes of 'res interface', they will be wrapped in Ref and return finally
  })
  const onAddQuickAccess = () => {}

  const returnState = {
    ...toRefs(renderData),
    onAddQuickAccess
  }

  provide(commDeviceKey, returnState)
  return returnState
}

export function useCommDevice(): CommDevice {
  return inject(commDeviceKey) as CommDevice
}
avatar
Mar 24th 2023

You can try ToRefs type and code below

type PartialRef<O, K extends keyof O> = ToRefs<Pick<O, K>> & Omit<O, K>

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBDAnmApnA3nAKhASigMwGcAaOfAuAXzgKghDgHIA3AVxSYChRJYM4KAB6oAxjCzIUAeUo06DZsLEwAtElTcuGtNIBGAKzgBeDFzi0IEAFxwiMKMAB2Ac3NwneQradsQelCguKi5tKTgABQBDWGAogBsKAB5pMgBpQSEYFCcAEyI4AGsURAhKaQA+E2wvYiSI4FFClPSKqoAyOGkQYBgWuDSK0J04AEFqnAoiFMMhgHo5izgAPQB+ULDUOAAhaujYhOT9AzImAismecWLNdDlFHFJVFkk7YqACgBKADoYCABRACObASTxkBCS6Hc5xs5EISXsjlcQwsngoPj8ASCVA+nyAA

I don't think this utility type is necessary to put in the vue core. You can create a 3rd party package if anyone like.

Thanks! It seems that my ts level is a little short 😂