Replies: 1 comment
-
It seems impossible in a general case.
If we have a static tree, then we can catch the issue in runtime. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
TL:DR;
What?
If we had something like
defineProvide
anddefineInject
that works howinject
/provide
does today but give the compiler more metadata. We could(?) leverage the vue compiler to know when aninject
-call is faulty and introduce a build error.How?
If we can decorate the components that provides data to their children with an
defineProvide
, if the vue compiler can turn your app into a tree of components, then it should be able to see if a component that usesdefineInject
which is not a ancestor of a component thatdefineProvide
'd of the data and check for misuse.And?
If this was a thing, we could write something I've been day dreaming about. Some sort of route-level state which you don't send as props, but use like global state for that route. Imagine if
/todos/:todoId
and all components that under that route had a shared state which is not in scope of all other routes. No default initializer that you would have to set because your state management framework is global and accessible through all routes.In more detail
The problem with
provide
/inject
vue APIs is that when you useinject
in a context where you know something has been provided, your inject call will returnT | undefined
. I understand that theundefined
call here is for safety. But that means I have to introduce weird if statements in my view:This is just typescript being typescript. There's nothing you can do about that. Typescript cannot infer that your provide call has happened in another component. That's just the reality, it doesn't have the context around it like you do.
From the inject/provide typing docs, it says this
and
I would like to challenge this thinking.
From provide / inject docs
If a parent has provided something. Is that not a guarantee enough that children has the required data? I don't know much about vue internals, but if there's just a matter of checking the component trees which has made the provide/inject calls. Is this not a solved problem? If you can "register" your provide/inject-usage. Can not the compiler help out here and tell you very sternly what you are trying to do is not allowed?
If this was a thing. Let's imagine for a second that it would be a solved problem and we can use AST to check that components are providing its proper data that descendant are injecting. I would make a scoped state management framework for vue.
Today, most of us using vue 3 are using pinia. It's working great so far but there are some caveats, which has nothing to do with the framework. But rather, the architecture and how the typescript compiler/language server doesn't have all the context.
Two paragraphs of rant coming up, bear with me.
Imagine if you are building the gaming application Steam, but in a web app. To play games, chat with friends or buy things you need to be logged in. Let's say that 99% of steam is behind a login screen.
Let's say we use pinia, which in nature is global state handler. You would need to something like:
What's wrong? Well, for every single consumer of our
userstore
. We need to do a check against undefined because our store has been initialized withundefined
as a default value.Remember, our app is 99% behind a login screen. That means that for every single view and component in our app we need to check against
undefined
, even though we know that it's never going to beundefined
because of the log in screen is gating this for us. This context is lost to the typescript compiler.You can read more about this rant, here
My ultimate goal would be to be able to write scoped state that just works for a certain part of the application. And if there's misuse through a component that is not an ancestor of the injected state, then I would find it amazing if the compiler could yell at me, telling me I shouldn't do this.
A scoped state management framework
Here's my quick and dirty implementation of a the APIs of my idea:
Questions
<component>
and<router-view>
could have some trouble deciphering this data. But that's just from an outside perspective.provide
/inject
with metadata to the compiler with sufficient information through the macro system that we have for other composition API solutions?inject
-call asT
instead ofT | undefined
and instead letting the compiler do the work for us?Beta Was this translation helpful? Give feedback.
All reactions