Skip to content

[Type for Reactivity Transform] Add another type which indicates the value is deconstructed from defineProps / 为 响应性语法糖 添加一个可以标识变量是从 defineProps 中解构出来的类型 #6876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xsjcTony opened this issue Oct 13, 2022 · 10 comments

Comments

@xsjcTony
Copy link

What problem does this feature solve?

English:

It's related to #5976 and #6578, please have a look at these two issues first.

I've investigated the types of Reactivity Transform, and I think we need to add another type to indicate whether the value is deconstructed from defineProps to solve the issue.

Currently, we have no way to know whether the developer wants to:
Scenario 1: use $$(Array) for deconstructing an array, like in watch

const refA = $ref(0)
const refB = $ref(0)

watch($$([refA, refB]), () => {})

Scenario 2: use $$(Array) for keeping the reactivity of the array, like using on Arrays deconstructed from defineProps

interface CompProps {
  arr: string[]
}
const { arr } = defineProps<CompProps>()

passAsRef($$(arr)) // Type for $$(arr) here is `Ref<string>[]` instead of `Ref<string[]>`

So the current type in macros.d.ts cannot solve the issue, as we have no idea what is the purpose of using $$() on an array.
If we add this

export declare function $$<T extends unknown[]>(value: T): Ref<T>

It solves Scenario 2 but breaks Scenario 1 so it's not a valid fix. (It's only an issue about the type, the runtime compilation is working as expected)

Maybe there's some other way to fix it, but I've tried my best.


中文:

请先阅读 #5976#6578, 该提议和这两个问题有关.

我看了一下 响应性语法糖 的类型, 我觉得需要添加一个额外的类型来标识从 defineProps() 解构出来的响应式变量 (以和其他的通过语法糖生成的响应式变量区分开) 来解决这个问题.

目前我们没法知道一个开发者想通过哪种方式在 数组 上使用 $$()
情况1: 通过 $$(Array) 解构数组, 让其中的每一个变量都保留响应式, 比如在 watch

const refA = $ref(0)
const refB = $ref(0)

watch($$([refA, refB]), () => {})

情况2: 通过 $$(Array) 使从 defineProps() 解构得到的数组保持响应性, 比如传递给需要接收 Ref 的函数

interface CompProps {
  arr: string[]
}
const { arr } = defineProps<CompProps>()

passAsRef($$(arr)) // 这里 $$(arr) 的类型为 `Ref<string>[]`, 而正确的应该是 `Ref<string[]>`

目前在 macros.d.ts 中的类型不足以解决问题, 因为我们不知道作用在数组上的 $$() 到底是什么作用.
如果加上这一个额外定义

export declare function $$<T extends unknown[]>(value: T): Ref<T>

它确实解决了 情况2, 但同时破坏了 情况1, 所以这样是不对的. (仅仅是一个类型问题, 运行时编译一切正常)

可能有其他方法能解决这个问题, 但是我尽力了. 太菜了😭

What does the proposed API look like?

English:

My ideal way is to add a type indicating that the value is deconstructed from defineProps(), e.g. in runtime-core.d.ts

// Before
export declare function defineProps<TypeProps>(): Readonly<TypeProps>;
// After
export type ValueFromProps<T> = T & { /* some indicators here */ }
export declare function defineProps<TypeProps>(): Readonly<ValueFromProps<TypeProps>>;

and in macros.d.ts

// Something similar to this
export declare function $$<T>(value:  ValueFromProps<T>): ToRawRefsForProps<T> 
type ToRawRefsForProps<T> = {
  T extends Array<infer V> // It may be incorrect, just an idea
    ? Ref<V>
    : // handle other objects and primitive types just like `ToRawRefs<T>` and other `$$()` types declared now.

中文:

我理想的解决方法是添加一个可以标识某个变量是从 defineProps() 解构出来的类型, 比如在 runtime-core.d.ts

// 以前
export declare function defineProps<TypeProps>(): Readonly<TypeProps>;
// 现在
export type ValueFromProps<T> = T & { /* some indicators here */ }
export declare function defineProps<TypeProps>(): Readonly<ValueFromProps<TypeProps>>;

macros.d.ts

// 类似这样的东西
export declare function $$<T>(value:  ValueFromProps<T>): ToRawRefsForProps<T> 
type ToRawRefsForProps<T> = {
  T extends Array<infer V> // 只是表达一个想法
    ? Ref<V>
    : // 处理其他对象和基本类型, 就像现在 `ToRawRefs<T>` 和其他 `$$()` 类型中的那样
@xsjcTony xsjcTony added the ✨ feature request New feature or request label Oct 13, 2022
@xsjcTony xsjcTony changed the title [Type for Reactivity Transform] Add another type which indicates the value is deconstructed from defineProps [Type for Reactivity Transform] Add another type which indicates the value is deconstructed from defineProps (中英双语) Oct 13, 2022
@xsjcTony xsjcTony changed the title [Type for Reactivity Transform] Add another type which indicates the value is deconstructed from defineProps (中英双语) [Type for Reactivity Transform] Add another type which indicates the value is deconstructed from defineProps / 为 响应性语法糖 添加一个可以标识变量是从 defineProps 中解构出来的类型 Oct 13, 2022
@sxzz
Copy link
Member

sxzz commented Oct 13, 2022

According to RFC Unresolved Questions chapter, I think we should have $defineProps or $(defineProps()) to fix it.

@sxzz
Copy link
Member

sxzz commented Oct 13, 2022

Here are the very prototype of definitions FYR:

<script lang="ts" setup>
type Props = {
  someArray: string[];
};
//      ⬇️ ReactiveVariable<string[]>
const { someArray } = $defineProps<Props>();

//     ⬇️ Ref<string[]>
const someArrayRef = $$(someArray);
</script>
/// <reference types="vue/macros-global" />

import type { RefValue } from "vue/macros";

declare global {
  function $defineProps<TypeProps>(): {
    [Key in keyof TypeProps]: RefValue<TypeProps[Key]>;
  };
}

export {};

@xsjcTony
Copy link
Author

Yeah seems like a valid fix. I'll keep an eye on it.
Not sure if I'm going to subscribe to the RFC as it may result in too many emails.

@sxzz
Copy link
Member

sxzz commented Oct 13, 2022

I guess we should wait for Evan to make the decision on RFC. If there's any news, I'll ping you on this issue.

@xsjcTony
Copy link
Author

Great, thanks. Guess I can learn a lot from the official fix.

@StepanMynarik
Copy link

Here are the very prototype of definitions FYR:

<script lang="ts" setup>
type Props = {
  someArray: string[];
};
//      ⬇️ ReactiveVariable<string[]>
const { someArray } = $defineProps<Props>();

//     ⬇️ Ref<string[]>
const someArrayRef = $$(someArray);
</script>
/// <reference types="vue/macros-global" />

import type { RefValue } from "vue/macros";

declare global {
  function $defineProps<TypeProps>(): {
    [Key in keyof TypeProps]: RefValue<TypeProps[Key]>;
  };
}

export {};

Same problem here.
Your suggested solution looks perfect btw!

@sxzz
Copy link
Member

sxzz commented Nov 4, 2022

Implemented in Vue Macros.
Read the Docs

@xsjcTony
Copy link
Author

xsjcTony commented Nov 5, 2022

Implemented in Vue Macros. Read the Docs

Thanks, that seems good. Will have a try later on.

@xsjcTony xsjcTony closed this as completed Nov 5, 2022
@sxzz
Copy link
Member

sxzz commented Nov 5, 2022

I think we should open this issue for official implementation tracking.

@sxzz
Copy link
Member

sxzz commented Mar 30, 2023

#7986
We have deprecated the Reactivity Transform and extracted the feature of reactive props destructuring to another option. This means that we no longer support $$, and users must use computed(() => foo) themselves. As a result, this issue has been bypassed.

@sxzz sxzz closed this as completed Mar 30, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Sep 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants