Skip to content

Commit 9026f26

Browse files
committed
Merge branch 'next'
2 parents 82aa0e5 + 749f5b8 commit 9026f26

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1949
-1883
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
dist
22
node_modules
3+
shim

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,5 @@ Icon
5151
.Spotlight-V100
5252
.Trashes
5353
dist
54+
shim/*.*
55+
!shim/package.json

.node-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
14.17.4
1+
14.17.5

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
14.17.4
1+
14.17.5

__tests__/jest.setup.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
/* eslint-env jest */
2+
console.log = jest.fn()
23
console.warn = jest.fn()
4+
console.error = jest.fn()
5+
console.debug = jest.fn()
6+
console.info = jest.fn()

__tests__/utils.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import * as utils from '../src/utils'
2-
import { VueTypeDef } from '../src/types'
2+
import { VueTypeDef } from '../src'
3+
import { config } from '../src'
4+
5+
beforeEach(() => {
6+
config.logLevel = 'warn'
7+
config.silent = false
8+
})
39

410
describe('`getType()`', () => {
511
it('return the type constructor as a string', () => {
@@ -331,3 +337,39 @@ describe('`fromType()`', () => {
331337
expect(validatorCopy.mock.instances[0]).toBe(copy as any)
332338
})
333339
})
340+
341+
describe('`warn()`', () => {
342+
it('calls `console.warn` by default', () => {
343+
const message = 'message'
344+
utils.warn(message)
345+
expect(console.warn).toHaveBeenCalledWith(`[VueTypes warn]: ${message}`)
346+
})
347+
348+
it('calls `console.log` if `config.logLevel` is `log`', () => {
349+
config.logLevel = 'log'
350+
const message = 'message'
351+
utils.warn(message)
352+
expect(console.log).toHaveBeenCalledWith(`[VueTypes warn]: ${message}`)
353+
})
354+
355+
it('calls `console.error` if `config.logLevel` is `error`', () => {
356+
config.logLevel = 'error'
357+
const message = 'message'
358+
utils.warn(message)
359+
expect(console.error).toHaveBeenCalledWith(`[VueTypes warn]: ${message}`)
360+
})
361+
362+
it('calls `console.debug` if `config.logLevel` is `debug`', () => {
363+
config.logLevel = 'debug'
364+
const message = 'message'
365+
utils.warn(message)
366+
expect(console.debug).toHaveBeenCalledWith(`[VueTypes warn]: ${message}`)
367+
})
368+
369+
it('calls `console.info` if `config.logLevel` is `info`', () => {
370+
config.logLevel = 'info'
371+
const message = 'message'
372+
utils.warn(message)
373+
expect(console.info).toHaveBeenCalledWith(`[VueTypes warn]: ${message}`)
374+
})
375+
})

__tests__/validators/oneoftype.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { string, integer } from '../../src/validators/native'
1+
import { string, integer, any } from '../../src/validators/native'
22
import oneOf from '../../src/validators/oneof'
33
import shape from '../../src/validators/shape'
44
import oneOfType from '../../src/validators/oneoftype'
@@ -65,4 +65,9 @@ describe('`.oneOfType`', () => {
6565

6666
expect(validator({ id: 2 })).toBe(false)
6767
})
68+
69+
it('should validate edge cases with null and true', () => {
70+
expect(oneOfType([any()]).type).toBe(null)
71+
expect(oneOfType([{ type: true }]).type).toBe(null)
72+
})
6873
})

docs/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ module.exports = {
4040
children: [
4141
'/advanced/extending-vue-types',
4242
'/advanced/custom-instance',
43+
'/advanced/typescript',
4344
],
4445
},
4546
],

docs/advanced/typescript.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# TypeScript Usage
2+
3+
VueTypes is written in TypeScript and comes with full builtin types support.
4+
5+
Most of the validators can infer the prop type from their configuration:
6+
7+
```ts
8+
props: {
9+
// prop type is `string`
10+
name: string(),
11+
// ERROR: Argument of type 'boolean' is not assignable to parameter of type 'string'
12+
surname: string().def(false),
13+
}
14+
```
15+
16+
## Optional type constraint
17+
18+
Some validators accepts an optional type argument to refine their TS typing.
19+
20+
### any<T = any>
21+
22+
```ts
23+
props: {
24+
unknownProp: any<unknown>()
25+
}
26+
```
27+
28+
### string<T = string>
29+
30+
Accepts both strings and enums.
31+
32+
```ts
33+
props: {
34+
// use a union type to constrain the string type
35+
color: string<'red' | 'green'>()
36+
}
37+
38+
enum Colors {
39+
red = 'red'
40+
green = 'green'
41+
}
42+
43+
props: {
44+
// same as above, but with an enum
45+
color: string<Colors>()
46+
}
47+
```
48+
49+
::: tip
50+
The same prop type can be expressed using `oneOf` which will also perform a validation at runtime:
51+
52+
```ts
53+
props: {
54+
genre: oneOf(['red', 'green'] as const)
55+
}
56+
```
57+
58+
:::
59+
60+
### number<T = number> and integer<T = number>
61+
62+
```ts
63+
props: {
64+
// use a union type to constrain the number type
65+
count: number<1 | 2>()
66+
67+
countInt: integer<1 | 2>()
68+
}
69+
```
70+
71+
### func<T = (...args: any[]) => any>
72+
73+
Useful to type event handlers and function return types.
74+
75+
```ts
76+
type EventFn = (e: Event) => void
77+
type AsyncFn = () => Promise<string[]>
78+
79+
props: {
80+
onClick: fn<EventFn>()
81+
loadStrings: fn<AsyncFn>()
82+
}
83+
```
84+
85+
### object<T = { [key: string]: any }>
86+
87+
```ts
88+
interface User {
89+
name: string
90+
// ...
91+
}
92+
93+
props: {
94+
user: object<User>()
95+
}
96+
```
97+
98+
::: tip
99+
To have both compile-time and runtime validation, you can use `shape`:
100+
101+
```ts
102+
interface User {
103+
name: string
104+
// ...
105+
}
106+
107+
props: {
108+
user: shape<User>({
109+
name: string().isRequired,
110+
})
111+
}
112+
```
113+
114+
:::
115+
116+
### array<T = unknown>
117+
118+
The validator accepts an argument defining the contained items type.
119+
120+
```ts
121+
interface User {
122+
name: string
123+
// ...
124+
}
125+
126+
props: {
127+
// array of numbers
128+
sizes: array<number>()
129+
// array of users
130+
users: array<User>()
131+
}
132+
```
133+
134+
::: tip
135+
The same prop types can be expressed using `arrayOf` which will also perform a validation at runtime:
136+
137+
```ts
138+
interface User {
139+
name: string
140+
// ...
141+
}
142+
143+
props: {
144+
sizes: arrayOf(Number)
145+
// set the object() validator type to User
146+
users: arrayOf(object<User>())
147+
}
148+
```
149+
150+
:::
151+
152+
### OneOfType\<T>
153+
154+
You can use a union type to specify the expected types.
155+
156+
```ts
157+
interface User {
158+
name: string
159+
// ...
160+
}
161+
162+
props: {
163+
// string or instance of User
164+
theProp: oneOfType<string | User>([String, Object])
165+
}
166+
```
167+
168+
::: tip
169+
The same prop types can be expressed composing VueTypes validators:
170+
171+
```ts
172+
interface User {
173+
name: string
174+
// ...
175+
}
176+
177+
props: {
178+
// same as above
179+
theProp: oneOfType([String, object<User>()])
180+
}
181+
```
182+
183+
:::
184+
185+
### shape\<T>
186+
187+
Setting the type argument provides type checking on top of runtime validation:
188+
189+
```ts
190+
interface User {
191+
name: string
192+
id?: string
193+
}
194+
195+
props: {
196+
user: shape<User>({
197+
name: string().isRequired,
198+
id: string(),
199+
})
200+
}
201+
```
202+
203+
### custom\<T>
204+
205+
You can define the type of the value received by the validator function.
206+
207+
```ts
208+
props: {
209+
// function argument is of type string
210+
nonEmptyString: custom<string>((v) => typeof v === 'string' && v.length > 0)
211+
}
212+
```
213+
214+
::: tip
215+
This validator can be used for tuple props:
216+
217+
```ts
218+
type Pair = [string, number]
219+
220+
props: {
221+
tuple: custom<Pair>(
222+
([a, b]) => typeof a === 'string' && typeof b === 'number',
223+
)
224+
}
225+
```
226+
227+
:::
228+
229+
### oneOf
230+
231+
This validator does not support type arguments, but you can use [const assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) on the expected values to constrain the validators type:
232+
233+
```ts
234+
props: {
235+
// ERROR: Argument of type '"small"' is not assignable
236+
// to parameter of type '"large" | "medium"'.
237+
sizes: oneOf(['large', 'medium'] as const).def('small')
238+
}
239+
```

docs/guide/configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ VueTypes.config === config
2020

2121
## Configuration Options
2222

23-
At the moment, there is only one configuration option:
24-
2523
- `silent`: (boolean, default `false`) set to `true` to prevent VueTypes from logging validation warnings.
2624

2725
::: tip
@@ -37,3 +35,5 @@ config.silent = Vue.config.silent
3735
```
3836

3937
:::
38+
39+
- `logLevel`: (string, default `warn`) allows choosing which console method will be used to display validation errors. Available options are `log`, `warn`, `error`, `debug` and`info`.

0 commit comments

Comments
 (0)