Description
What problem does this feature solve?
Let's say, there's a situation sometime that requires a user of Vue 3 to make a certain wrapper or extension for the standard public API.
For example...
Currently, there's only one way to define props for a functional component, as stated in docs:
import { h } from 'vue';
// extended to a more realistic example
// here, in TS, a user has to define props separately in two places, which produces code duplication
const DynamicHeading = (props: { level: number }, context) => {
return h(`h${props.level}`, context.attrs, context.slots);
};
DynamicHeading.props = {
level: Number;
};
export default DynamicHeading;
This is far from perfect for user experience, and is definitely in need of some sort of a wrapper (with type inference, preferably).
Something like
import { h } from 'vue';
// No code duplication whatsoever!
export default withProps({
level: Number;
}, (props, context) => {
// here props.level is already defined
return h(`h${props.level}`, context.attrs, context.slots);
});
The defineComponent
function is public and uses some typings to provide type information for the component and props alike, which would also be useful for this wrapper.
I've written this wrapper myself for my project only, but have encountered an issue - currently most of the types of @vue/runtime-core
are internal and are not exported, therefore making a job of creating such wrappers practically an impossible choice.
So, now you either:
- do not write any wrappers at all and live with boilerplate code, which is painful;
- or practically copy over half of
@vue/runtime-core/dist/runtime-core.d.ts
into the project, because most of the types used indefineComponent
are not exposed.
So, with all types exported from d.ts files, the end user gains the ability to more freely understand and expand upon the standard Vue 3 API without the need to write boilerplate code or copy half of the typings into their own project.
The wrapper is still possible to create without vue typings, it's just an example. But it still would lack some typing clarity the internal types could provide...
What does the proposed API look like?
Export all types without exceptions from d.ts
files so users can more freely extend and compose current API properly (this was the whole point from the start, right?)...
This can be done with existing APIs, as no new APIs need to be added - just a couple of exports for compile-time types here and there.
I get that there are some types that are used only by internal APIs that are not exposed, and it may be okay.
But there are types used by public APIs (like defineComponent
), that are still not exposed.
So, not exposing types used by public APIs is like not exposing some part of the already exposed API.
In my opinion, exposed types allow for:
- a more cohesive substitution techniques - user doesn't have to fork Vue to replace any part of its API - a couple of imported types is enough to maintain guaranteed type symmetry and LSP;
- ability to fix bugs in-place without the need to wait until Vue team fixes them or approves a fix (and without forks);
P.S. If this gets any positive feedback - I'll gladly propose a PR myself.
P.P.S. The issue itself is more about the lack of type exports than the wrapper itself - it's provided as more of an example of what's to come (in terms of user experience problems) when Vue 3 makes it to production and is adopted by industry-scale projects.