-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Support MaybeRefOrGetter
as the type for passing props
#8842
Comments
<DateLabel :value="dateGetter()" /> |
@Shyam-Chen I could be wrong but I believe there is a distinct difference between that and what I'm asking for. A getter normalized to a ref using
|
Use <script lang="ts" setup>
import { ref, computed } from 'vue';
import DateLabel from './DateLabel.vue';
const dateConst = new Date();
const dateRef = ref(new Date());
const dateGetter = computed(() => new Date());
</script>
<template>
<DateLabel :value="dateConst" />
<DateLabel :value="dateRef" />
<DateLabel :value="dateGetter" />
</template>
<script lang="ts" setup>
const props = defineProps<{
value: Date;
bar?: number;
}>();
</script>
<template>
<div>{{ value.toLocaleString() }}</div>
</template> |
@Shyam-Chen There are a few key differences between computed and getters which are outlined quite well in #7997. Both methods you've suggested are possible and useful. However they are functionally and performantly differently than being able to pass a getter that is then normalized in the receiving component. |
This may be a misunderstanding. You cannot pass a ref, props do not have a // code generated by the SFC compiler
render: () => h(DateLabel, { date: unref(dateRef) }) So the child never receives the ref, it always receives the value - a To do a similar thing with a getter, you would do what @Shyam-Chen initially proposed - you would evaluate the getter in the template. <DateLabel :date="dateGetter()" /> Now, if you want the getter to be evaluated in the child, only when the prop is actually used there, then you would need to write your component to support that. <script lang="ts" setup>
import { ref } from 'vue'
const { date } = defineProps<{
date: Date | () => Date
}>()
</script>
<template>
{{ typeof date === 'function' ? date() : date }}
</template> I kind of understand that you want this to happen automatically, but I'm not sure where and when. We can't "unwrap" getters in the parent automatically like we do refs, because getters are just functions - and so far, we do allow passing a function as a prop value to a child. If we decided to suddenly "unwrap" (call) all functions we pass as props, we would certainly break lots and lots of userland code, so this is not going to happen. Similarly, unwrapping it with some "magic" in the props in the child on each access would break existing userland code all the same. |
@pleek91 Can you probvide feedback to what I layed out here? Otherwise I would close this request as it's not really possible in the way that I understand your request to work. |
@LinusBorg thanks for the detailed response. That totally makes sense. I guess I'm suggesting that when the template is converted into a render function to use I was thinking about this from a pure types perspective where currently if you're using typescript the type for a prop that is a In my project I am currently doing what you suggested by making a Thanks again for the detailed explanation! |
What problem does this feature solve?
Getters are extremely useful to avoid the overhead of computed properties and to pass data that should be re-evaluated when accessed. So something like
() => new Date()
vsnew Date()
. #7997 is great and provides some nice tools for handling getters and normalizing values specifically theMaybeRefOrGetter
type and thetoValue
andtoRef
utilities.Props basically have the type
MaybeRef
because you can bind either a static value or a ref:value="new Date()"
vs:value="myDateRef"
. However you cannot pass a getter. Currently in order to do so you'd have to make the type for your propDate | (() => Date)
and then normalize the value usingtoRef
ortoValue
inside your component. Then you could pass:value="myDateGetter"
.It would be a nice developer experience to allow all props to be
MaybeRefOrGetter
and automatically normalize the value. So you could bindmyDateGetter
while the prop type would simplyDate
.What does the proposed API look like?
DateLabel.vue
When using the
DateLabel
component all three of these would pass type validation and render the date label.The text was updated successfully, but these errors were encountered: