File tree Expand file tree Collapse file tree 5 files changed +93
-2
lines changed Expand file tree Collapse file tree 5 files changed +93
-2
lines changed Original file line number Diff line number Diff line change @@ -34,6 +34,7 @@ The validation errors are detailed. Adapted from the brilliant work in `flow-run
34
34
- [ ` t.simpleObject({ foo: t.string() }) ` ] ( #tsimpleobject-foo-tstring- )
35
35
- [ ` t.object ` ] ( #tobject )
36
36
- [ ` t.record(t.string(), t.number()) ` ] ( #trecordtstring-tnumber )
37
+ - [ ` t.instanceof(Date) ` ] ( #tinstanceofdate )
37
38
- [ ` t.tuple(t.string(), t.number()) ` ] ( #ttupletstring-tnumber )
38
39
- [ ` t.allOf(A, B) ` ] ( #tallofa-b )
39
40
- [ ` t.oneOf(t.string(), t.number()) ` ] ( #toneoftstring-tnumber )
@@ -259,6 +260,10 @@ You can also use the `t.optionalNullOr(t.string())` as a shorthand for
259
260
260
261
A validator that requires the value to be ` Record <string , number >` .
261
262
263
+ ### ` t .instanceOf (Date )`
264
+
265
+ A validator that requires the value to be an instance of ` Date ` .
266
+
262
267
### ` t .tuple (t .string (), t .number ())`
263
268
264
269
A validator that requires the value to be ` [string , number ]` .
Original file line number Diff line number Diff line change @@ -3,8 +3,10 @@ import { keyToString } from './keyToString'
3
3
export default function typeOf ( value : any ) : string {
4
4
if ( value == null ) return String ( value )
5
5
if ( typeof value !== 'object' ) return typeof value
6
- if ( value . constructor && value . constructor !== Object )
7
- return value . constructor . name
6
+ const constructor = value . prototype
7
+ ? value . prototype . constructor
8
+ : value . constructor
9
+ if ( constructor && constructor !== Object ) return constructor . name
8
10
return `{\n${ Object . keys ( value )
9
11
. map ( key => ` ${ keyToString ( key ) } : ${ typeOf ( value [ key ] ) } ` )
10
12
. join ( ',\n' ) } \n}`
Original file line number Diff line number Diff line change @@ -3,6 +3,7 @@ import AnyType from './types/AnyType'
3
3
import ArrayType from './types/ArrayType'
4
4
import BooleanLiteralType from './types/BooleanLiteralType'
5
5
import BooleanType from './types/BooleanType'
6
+ import InstanceOfType from './types/InstanceOfType'
6
7
import IntersectionType from './types/IntersectionType'
7
8
import NullLiteralType from './types/NullLiteralType'
8
9
import UndefinedLiteralType from './types/UndefinedLiteralType'
@@ -28,6 +29,7 @@ export {
28
29
ArrayType ,
29
30
BooleanLiteralType ,
30
31
BooleanType ,
32
+ InstanceOfType ,
31
33
IntersectionType ,
32
34
NullLiteralType ,
33
35
UndefinedLiteralType ,
@@ -171,6 +173,10 @@ export const record = <K extends string | number | symbol, V>(
171
173
value : Type < V >
172
174
) : RecordType < K , V > => new RecordType ( key , value )
173
175
176
+ export const instanceOf = < T extends { new ( ...args : any [ ] ) : any } > (
177
+ classType : T
178
+ ) : Type < T > => new InstanceOfType ( classType )
179
+
174
180
export const tuple = < T extends Type < any > [ ] > (
175
181
...types : T
176
182
) : Type < { [ Index in keyof T ] : T [ Index ] extends Type < infer E > ? E : never } > =>
Original file line number Diff line number Diff line change
1
+ import * as t from './'
2
+ import { expect } from 'chai'
3
+ import dedent from 'dedent-js'
4
+
5
+ class Foo { }
6
+
7
+ describe ( `t.instanceOf` , function ( ) {
8
+ it ( `accepts instances of class type` , function ( ) {
9
+ t . instanceOf ( Date ) . assert ( new Date ( ) )
10
+ t . instanceOf ( Foo ) . assert ( new Foo ( ) )
11
+ expect ( t . instanceOf ( Date ) . accepts ( new Date ( ) ) ) . to . be . true
12
+ expect ( t . instanceOf ( Foo ) . accepts ( new Foo ( ) ) ) . to . be . true
13
+ } )
14
+ it ( `rejects not instances of class type` , function ( ) {
15
+ expect ( ( ) => t . instanceOf ( Date ) . assert ( { } ) ) . to . throw (
16
+ t . RuntimeTypeError ,
17
+ dedent `
18
+ Value must be an instance of Date
19
+
20
+ Expected: Date
21
+
22
+ Actual Value: {}
23
+
24
+ Actual Type: {
25
+
26
+ }`
27
+ )
28
+ expect ( t . instanceOf ( Date ) . accepts ( new Foo ( ) ) ) . to . be . false
29
+ expect ( ( ) => t . instanceOf ( Date ) . assert ( new Foo ( ) ) ) . to . throw (
30
+ t . RuntimeTypeError ,
31
+ dedent `
32
+ Value must be an instance of Date
33
+
34
+ Expected: Date
35
+
36
+ Actual: Foo`
37
+ )
38
+ expect ( t . instanceOf ( Date ) . accepts ( new Foo ( ) ) ) . to . be . false
39
+ } )
40
+ } )
Original file line number Diff line number Diff line change
1
+ import Type from './Type'
2
+
3
+ import getErrorMessage from '../getErrorMessage'
4
+ import Validation , { ErrorTuple , IdentifierPath } from '../Validation'
5
+
6
+ export default class InstanceOfType <
7
+ T extends { new ( ...args : any [ ] ) : any }
8
+ > extends Type < T > {
9
+ typeName = 'InstanceOfType'
10
+ classType : T
11
+
12
+ constructor ( classType : T ) {
13
+ super ( )
14
+ this . classType = classType
15
+ }
16
+
17
+ * errors (
18
+ validation : Validation < any > ,
19
+ path : IdentifierPath ,
20
+ input : any
21
+ ) : Generator < ErrorTuple , void , void > {
22
+ if ( ! ( input instanceof this . classType ) ) {
23
+ yield [
24
+ path ,
25
+ getErrorMessage ( 'ERR_EXPECT_INSTANCEOF' , this . toString ( ) ) ,
26
+ this ,
27
+ ]
28
+ }
29
+ }
30
+
31
+ accepts ( input : any ) : boolean {
32
+ return input instanceof this . classType
33
+ }
34
+
35
+ toString ( ) : string {
36
+ return this . classType . prototype . constructor . name
37
+ }
38
+ }
You can’t perform that action at this time.
0 commit comments