Skip to content

Commit 67c332f

Browse files
committed
Merge branch 'release/1.5.0'
2 parents f03ec96 + f8e19c7 commit 67c332f

25 files changed

+20153
-19373
lines changed

README.md

+113
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- [Native Types](#native-types)
1919
- [Native Types Configuration](#native-types-configuration)
2020
- [Custom Types](#custom-types)
21+
- [Extending VueTypes](#extending-vuetypes)
2122
- [Utilities](#utilities)
2223
- [License](#license)
2324

@@ -252,6 +253,25 @@ VueTypes.sensibleDefaults = {
252253
}
253254
```
254255
256+
Under the hood `VueTypes.sensibleDefaults` is a plain object with just some added _magic_. That let's you play with it like you'd do with every other object.
257+
258+
For example you can remove some of the default values by leveraging [object rest spread](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) or [lodash.omit](https://lodash.com/docs/4.17.11#omit) like functions.
259+
260+
```js
261+
// copy every default value but boolean
262+
263+
console.log(VueTypes.bool.default)
264+
// logs true
265+
266+
const { bool, ...newDefaults } = VueTypes.sensibleDefaults
267+
268+
VueTypes.sensibleDefaults = newDefaults
269+
// or VueTypes.sensibleDefaults = _.omit(VueTypes.sensibleDefaults, ['bool'])
270+
271+
console.log(VueTypes.bool.default)
272+
// logs undefined
273+
```
274+
255275
### Custom Types
256276
257277
Custom types are a special kind of types useful to describe complex validation requirements. By design each custom type:
@@ -428,6 +448,99 @@ export default {
428448
}
429449
```
430450
451+
### Extending VueTypes
452+
453+
You can extend VueTypes with your own types via `VueTypes.extend({...})`. The method accepts an object with every key supported by [Vue prop validation objects](https://vuejs.org/v2/guide/components-props.html#Prop-Validation) plus the following custom properties:
454+
455+
- `name`: (string, required) The type name. Will be exposed as VueType.<name>
456+
- `validate`: (boolean, default: `false`) If `true` the type will have a `validate` method like native types.
457+
- `getter`: (boolean, default: `false`) If `true` will setup the type as an accessor property (like, for example `VueTypes.string`) else will setup the type as a configurable method (like, for example `VueTypes.arrayOf`).
458+
459+
Examples:
460+
```js
461+
// as an accessor type
462+
VueTypes.extend({
463+
name: 'negative',
464+
getter: true,
465+
type: Number,
466+
validator: (v) => v < 0
467+
})
468+
469+
const negativeProp = VueTypes.negative
470+
471+
// as a configurable method
472+
VueTypes.extend({
473+
name: 'negativeFn',
474+
type: Number,
475+
validator: (v) => v < 0
476+
})
477+
478+
const negativeProp2 = VueTypes.negativeFn() // <-- we need to call it
479+
```
480+
481+
Note that if `getter` is set to `false`, arguments passed to the type will be passed to the `validator` method together with the prop value:
482+
483+
```js
484+
VueTypes.extend({
485+
name: 'maxLength',
486+
// getter: false, this is the default
487+
type: String,
488+
validator: (max, v) => v.length <= max
489+
})
490+
491+
const maxLengthType = VueTypes.maxLength(2)
492+
493+
maxLengthType.validator('ab') // true
494+
maxLengthType.validator('abcd') // false
495+
```
496+
497+
#### Typescript
498+
499+
When used in a TypeScript project, types added via `.extend()` might fail type checking. In order to instruct TypeScript about your custom types you can use the following pattern:
500+
501+
```ts
502+
// propTypes.ts
503+
504+
// import
505+
// - VueTypes library
506+
// - validation object interface (VueTypeDef)
507+
// - the default VueType interface (VueTypesInterface)
508+
import VueTypes, { VueTypeDef, VueTypesInterface } from 'vue-types'
509+
510+
interface ProjectTypes extends VueTypesInterface {
511+
//VueTypeDef accepts the prop expected type as argument
512+
maxLength(max: number): VueTypeDef<string>
513+
}
514+
515+
VueTypes.extend({
516+
name: 'maxLength',
517+
type: String,
518+
validator: (max: number, v: string) => v.length <= max
519+
})
520+
521+
export default VueTypes as ProjectTypes
522+
```
523+
524+
Then import the newly created `propTypes.ts` instead of `vue-types`:
525+
526+
```html
527+
<!-- MyComponent.vue -->
528+
<template>
529+
<!-- template here -->
530+
</template>
531+
<script lang="ts">
532+
import Vue from "vue";
533+
import VueTypes from "./prop-types";
534+
535+
export default Vue.extend({
536+
name: "MyComponent",
537+
props: {
538+
msg: VueTypes.maxLength(2)
539+
}
540+
});
541+
</script>
542+
```
543+
431544
### Utilities
432545
433546
`vue-types` exposes some utility functions on the `.utils` property:

dist/index.js

+47
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ var _sensibles = require("./sensibles");
1111

1212
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1313

14+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
15+
1416
var VueTypes = {
1517
get any() {
1618
return (0, _utils.toType)('any', {
@@ -72,6 +74,51 @@ var VueTypes = {
7274
}, true);
7375
},
7476

77+
extend: function extend(props) {
78+
if (props === void 0) {
79+
props = {};
80+
}
81+
82+
var _props = props,
83+
name = _props.name,
84+
_props$validate = _props.validate,
85+
validate = _props$validate === void 0 ? false : _props$validate,
86+
_props$getter = _props.getter,
87+
getter = _props$getter === void 0 ? false : _props$getter,
88+
type = _objectWithoutPropertiesLoose(_props, ["name", "validate", "getter"]);
89+
90+
var descriptor;
91+
92+
if (getter) {
93+
descriptor = {
94+
get: function get() {
95+
return (0, _utils.toType)(name, type, validate);
96+
},
97+
enumerable: true,
98+
configurable: false
99+
};
100+
} else {
101+
var validator = type.validator;
102+
descriptor = {
103+
value: function value() {
104+
if (validator) {
105+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
106+
args[_key] = arguments[_key];
107+
}
108+
109+
type.validator = validator.bind.apply(validator, [this].concat(args));
110+
}
111+
112+
return (0, _utils.toType)(name, type, validate);
113+
},
114+
writable: false,
115+
enumerable: true,
116+
configurable: false
117+
};
118+
}
119+
120+
return Object.defineProperty(this, name, descriptor);
121+
},
75122
custom: function custom(validatorFn, warnMsg) {
76123
if (warnMsg === void 0) {
77124
warnMsg = 'custom validation failed';

dist/shim.js

+11
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,16 @@ Object.defineProperty(vueTypes, 'shape', {
6666
});
6767
}
6868
});
69+
70+
vueTypes.extend = function (props) {
71+
var name = props.name,
72+
validate = props.validate,
73+
_props$getter = props.getter,
74+
getter = _props$getter === void 0 ? false : _props$getter;
75+
return createValidator(vueTypes, name, getter, validate && {
76+
validate: function validate() {}
77+
});
78+
};
79+
6980
var _default = vueTypes;
7081
exports.default = _default;

es/index.js

+47
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
2+
13
import isPlainObject from 'lodash/isPlainObject';
24
import { toType, getType, isFunction, validateType, isInteger, isArray, warn } from './utils';
35
import { setDefaults } from './sensibles';
@@ -62,6 +64,51 @@ var VueTypes = {
6264
}, true);
6365
},
6466

67+
extend: function extend(props) {
68+
if (props === void 0) {
69+
props = {};
70+
}
71+
72+
var _props = props,
73+
name = _props.name,
74+
_props$validate = _props.validate,
75+
validate = _props$validate === void 0 ? false : _props$validate,
76+
_props$getter = _props.getter,
77+
getter = _props$getter === void 0 ? false : _props$getter,
78+
type = _objectWithoutPropertiesLoose(_props, ["name", "validate", "getter"]);
79+
80+
var descriptor;
81+
82+
if (getter) {
83+
descriptor = {
84+
get: function get() {
85+
return toType(name, type, validate);
86+
},
87+
enumerable: true,
88+
configurable: false
89+
};
90+
} else {
91+
var validator = type.validator;
92+
descriptor = {
93+
value: function value() {
94+
if (validator) {
95+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
96+
args[_key] = arguments[_key];
97+
}
98+
99+
type.validator = validator.bind.apply(validator, [this].concat(args));
100+
}
101+
102+
return toType(name, type, validate);
103+
},
104+
writable: false,
105+
enumerable: true,
106+
configurable: false
107+
};
108+
}
109+
110+
return Object.defineProperty(this, name, descriptor);
111+
},
65112
custom: function custom(validatorFn, warnMsg) {
66113
if (warnMsg === void 0) {
67114
warnMsg = 'custom validation failed';

es/shim.js

+11
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,15 @@ Object.defineProperty(vueTypes, 'shape', {
6161
});
6262
}
6363
});
64+
65+
vueTypes.extend = function (props) {
66+
var name = props.name,
67+
validate = props.validate,
68+
_props$getter = props.getter,
69+
getter = _props$getter === void 0 ? false : _props$getter;
70+
return createValidator(vueTypes, name, getter, validate && {
71+
validate: function validate() {}
72+
});
73+
};
74+
6475
export default vueTypes;

examples/jsconfig.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"compilerOptions": {
3+
"baseUrl": "./",
4+
"paths": {
5+
"vue-types": ["../src/index.js"],
6+
"vue-types/types": ["../types/vue-types.d.ts"]
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)