vue-functional-props
Handle functional component props properly
It's a small side-effect-free library with a single purpose - provide Vue 3 devs a simple way of type-safe handling properties for functional components.
Installation
npm i -S vue-functional-props
or
yarn add vue-functional-props
Usage
npm:
npm i -S vue-functional-props
browser:
<!-- ES2015 --> <!-- ES5 with IE11+ general syntax polyfills, global object - `vue-functional-props` --><!-- Polyfill `window.Promise` and `Object.assign` yourself! -->
Importing:
// TS-module (pure typescript),// allows compilation settings to be set from the project config; // ES-module (npm/node, typescript); // ESNext (no polyfills for esnext); // ES-module (browser, node); // Classic node commonjs;
Documenation example
Official Vue 3 docs state that functional component props can only be added in one way:
; // here, in TS, a user has to define props separately in two places, which produces code duplication; DynamicHeading.props =; ;
This is far from perfect for user experience, and is definitely in need of some sort of a wrapper (with type inference, preferably).
This tiny (~300B gzipped) library allows to achieve just that!
; // No code duplication whatsoever!;
API
;
withProps
function withProps<P, S>(props: P, setup: S): S
A simple function wrapper that accepts a standard vue props object definition and a setup function and adds props to the setup function definition so they can be recognized by vue.
Usage with object prop notation:
withProps,;
Usage with an array notation:
withProps // `as const` cast is needed for array notation in order for TS to infer the type as const,;
component
function component(name: string, inheritAttrs: boolean = true)
Useful for when you need to define name, events and other properties,
but still need a functional component.
Note: it doesn't call
defineComponent
!
Returns a type-safe functional component builder with the following methods:
withProps
- identical to the exportedwithProps
, but accepts only one argument - props definition. Returns the same object as thecomponent
function.emits
- accepts a map of event declaration like this. Returns the same object as thecomponent
function.setup
- accepts the functional component itself, providing type-safety. Returns the component itself. Must be called last.
;; .emits .withProps .setup; /* Equivalent to:const DynamicHeading = (props, context) => { // Absolutely no typesafety here, everything is `any` return h(`h${props.level}`, { ...context.attrs, on: { click: e => context.emit('click', e) } }, context.slots);}; DynamicHeading.displayName = 'DynamicHeading';DynamicHeading.inheritAttrs = false;DynamicHeading.props = { level: { type: [Number, String], required: true, validator: level => Number(level) > 0 && Number(level) <= 6 }};DynamicHeading.emits = { click(e: MouseEvents) {}}; export default DynamicHeading;*/
withProps
and emits
can be called in any order or not called at all:
// Validcomponent'DynamicHeading', false .withProps .setup; // Also Validcomponent'DynamicHeading', false .emits .setup; // Also Validcomponent'DynamicHeading', false .setup; // INVALID!component'DynamicHeading', false .setup .emits;// .setup must be called last!
prop
function prop<T, D = T>(options: Prop<T, D>): () => Prop<T, D>
T
- a complex type for the prop.
D
- provide if default differs from T
.
Enables type validaton for complex types in props without the need to pass constructors or runtime validators.
Basically, a NOOP without TypeScript.
Currently needs to be an empty function, that retutns a function which accepts the prop options, like this:
prop // Empty function call
This is needed to infer the option type correctly due to a design flaw in TypeScript.
; // Some complex objects, for exampledeclare declare ;
Contribute
First, fork the repo and clone it:
git clone https://github.com/%your-github-username%/vue-functional-props.git
Then:
npm install
Then:
npm run dev
Then introduce changes and propose a PR!
I'll be happy to review it!
Something's missing or found a bug?
Feel free to create an issue!