Skip to content
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

Type for T | Ref<T> #1366

Closed
jods4 opened this issue Jun 14, 2020 · 11 comments
Closed

Type for T | Ref<T> #1366

jods4 opened this issue Jun 14, 2020 · 11 comments
Labels

Comments

@jods4
Copy link
Contributor

jods4 commented Jun 14, 2020

What problem does this feature solve?

This is a small quality-of-life improvement.

Many libs and composables will accept potentially reactive inputs.
They will typically read those input by doing unref(x), which works on both plain values and refs.

So the following typing might become a common pattern:

// Typing
function useLength(input: string | Ref<string>): Ref<number>;

// Example uses
let s1 = "abc";
let l1 = useLength(s1);
let s2 = ref("123");
let l2 = useLength(s2);

What does the proposed API look like?

I think it would be convenient and set a common standard for everyone if Vue exported the following type (name up for bikeshedding):

export type RValue<T> = T | Ref<T>

Of course, everybody is free to declare such a type in userland.
I think it might be convenient to import it from "vue", which is an existing import in the source files; and it would give a common name to such inputs that every lib can use (familiarity for users).

It will also encourage library authors to accept RValue<T> inputs, rather than say, Ref<T>.

@pikax
Copy link
Member

pikax commented Jun 16, 2020

That's something I do quite a lot, as you said it can be done quite easily on userland.

My only concern here is the naming RValue, I don't think RValue is good enough name to be exported from the library.

@LinusBorg
Copy link
Member

LinusBorg commented Jun 21, 2020

I personally call them MaybeRef<T> in my codebases, as the argument may be a Ref, or not 🙃

@LinusBorg LinusBorg added the ✨ feature request New feature or request label Jun 21, 2020
@jacekkarczmarczyk
Copy link
Contributor

They will typically read those input by doing unref(x)

All my usages of MaybeRef (so far 1 xd) are actually getting T | ComputedRef<T> since I use this values only for reading - it makes me think that T | ComputedRef<T> is actually a better idea.

Is there even a usecase when I would want to pass T | Ref<T> and have possibility of updating the value of ref?

@LinusBorg
Copy link
Member

LinusBorg commented Jun 25, 2020

Is there even a usecase when I would want to pass T | Ref and have possibility of updating the value of ref?

I'd say there surely are usecases even though they might not be that many. But since Ref also matches for computed refs, it just is more convenient: People can pass a ref or computed ref, whichever they have at hand when calling your composable.

@jods4
Copy link
Contributor Author

jods4 commented Jun 25, 2020

@jacekkarczmarczyk

since I use this values only for reading

Computed has is not about reading, it can be read/write, too.
It's a ref that uses computations rather than being a plain value itself: think get/set property instead of field.

What you're saying is that a readonly ref might make more sense: T | readonly Ref<T>.
I'm not sure if that typing works but I agree 100% with you.
Since T can't be written to, I wouldn't expect the code to write to the ref either.

A MaybeRef should accept any kind of ref, including readonly refs: ref(1), computed(() => 1), readonly(ref(1)).

@jods4
Copy link
Contributor Author

jods4 commented Jun 25, 2020

I'd say there surely are usecases even though they might not be that many.

There's always corner cases, but then one can use something else than MaybeRef<T> for typing.
I see this type as a convenience and "standard" for the common case.

@jacekkarczmarczyk
Copy link
Contributor

jacekkarczmarczyk commented Jun 25, 2020

Computed has is not about reading, it can be read/write, too.

Well, not in this case:
image

Anyway you're right, I had readonly in mind, if you think that readonly Ref<T> is better than ComputedRef<T> then let it be, can I get an explanation though how would writing to ComputedRef be possible given the above example?

There's always corner cases, but then one can use something else than MaybeRef for typing.

+1

@jods4
Copy link
Contributor Author

jods4 commented Jun 25, 2020

What I meant is that -- as far as concepts go -- you can create writable computeds:
let x = computed({ get: ..., set: ... })

It looks like the type ComputedRef<T> is meant for the getter-only version.

Makes sense since a writable computed is exactly like Ref from the type-system perspective.
Then again the readonly computed is exactly like a readonly ref for the type-system, so now I'm a bit lost in the way the types are organized. 😵

No matter what the actual types are, I think the goal is this:

A MaybeRef should accept [...]: ref(1), computed(() => 1), readonly(ref(1)).

Plus plain T of course and you should be able to call unref on it.

@jacekkarczmarczyk
Copy link
Contributor

A MaybeRef should accept [...]: ref(1), computed(() => 1), readonly(ref(1)).

Plus plain T of course and you should be able to call unref on it.

If we agree on MaybeRef being readonly then it should be added to the above requirements. I'm not sure if it's a bug in vue typings or limitations of TS, but you can pass a readonly ref (or computed ref) to a function that accepts writable refs:

function t (x: Ref<number>) {
  x.value = 1;
}

t(computed(() => 1)); // should not be allowed

@skirtles-code
Copy link
Contributor

Evan has opened a PR that, among other things, adds MaybeRef: #7997.

@jd-solanki
Copy link

@LinusBorg I guess we can close this now as this is implemented: https://vuejs.org/api/utility-types.html#mayberef

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

No branches or pull requests

7 participants