File tree Expand file tree Collapse file tree 6 files changed +72
-1
lines changed
Expand file tree Collapse file tree 6 files changed +72
-1
lines changed Original file line number Diff line number Diff line change @@ -42,6 +42,7 @@ The validation errors are detailed. Adapted from the brilliant work in `flow-run
4242 - [ ` t.readonlyArray(t.number()) ` ] ( #treadonlyarraytnumber )
4343 - [ ` t.object(properties) ` ] ( #tobjectproperties )
4444 - [ ` t.object({ required?, optional?, exact? }) ` ] ( #tobject-required-optional-exact- )
45+ - [ ` t.opaque<DateString>(() => t.string()) ` ] ( #topaquedatestring--tstring )
4546 - [ ` t.readonly(objectType) ` ] ( #treadonlyobjecttype )
4647 - [ ` t.merge(...objectTypes) ` ] ( #tmergeobjecttypes )
4748 - [ ` t.mergeInexact(...objectTypes) ` ] ( #tmergeinexactobjecttypes )
@@ -386,9 +387,13 @@ PersonType.assert({ name: 1 }) // error
386387PersonType .assert ({ name: ' dude' , age: ' old' }) // error
387388```
388389
390+ ### ` t.opaque<DateString>(() => t.string()) `
391+
392+ A validator that requires the value to be a string, but presents the type as ` DateString ` (for instance with ` export opaque type DateString = string ` )
393+
389394### ` t.readonly(objectType) `
390395
391- Use ` t.readOnly (t.object(...)) ` or ` t.readOnly (t.merge(...)) ` etc. Doesn't require the object to be frozen, just allows the extracted type to be readonly.
396+ Use ` t.readonly (t.object(...)) ` or ` t.readonly (t.merge(...)) ` etc. Doesn't require the object to be frozen, just allows the extracted type to be readonly.
392397
393398### ` t.merge(...objectTypes) `
394399
Original file line number Diff line number Diff line change @@ -14,6 +14,7 @@ import NumberType from './types/NumberType'
1414import NumericLiteralType from './types/NumericLiteralType'
1515import ObjectType from './types/ObjectType'
1616import ObjectTypeProperty from './types/ObjectTypeProperty'
17+ import OpaqueType from './types/OpaqueType'
1718import oneOf from './oneOf'
1819import PrimitiveLiteralType from './types/PrimitiveLiteralType'
1920import RecordType from './types/RecordType'
@@ -47,6 +48,7 @@ export {
4748 NumericLiteralType,
4849 ObjectType,
4950 ObjectTypeProperty,
51+ OpaqueType,
5052 oneOf,
5153 PrimitiveLiteralType,
5254 RecordType,
@@ -68,6 +70,7 @@ export {
6870
6971declare export function any(): Type<any>
7072declare export function unknown(): Type<mixed>
73+ declare export function opaque<T>(type: () => Type<any>): OpaqueType<T>
7174
7275declare export function array<T>(elementType: Type<T>): Type<T[]>
7376declare export function readonlyArray<T>(
Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ import NumberType from './types/NumberType'
1212import NumericLiteralType from './types/NumericLiteralType'
1313import ObjectType from './types/ObjectType'
1414import ObjectTypeProperty from './types/ObjectTypeProperty'
15+ import OpaqueType from './types/OpaqueType'
1516import oneOf from './oneOf'
1617import PrimitiveLiteralType from './types/PrimitiveLiteralType'
1718import RecordType from './types/RecordType'
@@ -45,6 +46,7 @@ export {
4546 NumericLiteralType ,
4647 ObjectType ,
4748 ObjectTypeProperty ,
49+ OpaqueType ,
4850 oneOf ,
4951 PrimitiveLiteralType ,
5052 RecordType ,
@@ -66,6 +68,8 @@ export {
6668
6769export const any = ( ) : Type < any > => new AnyType ( )
6870export const unknown = ( ) : Type < unknown > => new UnknownType ( )
71+ export const opaque = < T > ( type : ( ) => Type < any > ) : OpaqueType < T > =>
72+ new OpaqueType < T > ( type )
6973
7074export const array = < T > ( elementType : Type < T > ) : Type < T [ ] > =>
7175 new ArrayType ( elementType )
Original file line number Diff line number Diff line change 1+ // @flow
2+
3+ import Type from './Type'
4+
5+ declare class OpaqueType<T> extends Type<T> {
6+ type: () => Type<any>;
7+
8+ constructor(type: () => Type<any>): void;
9+ }
10+
11+ export default OpaqueType
Original file line number Diff line number Diff line change 1+ import Type from './Type'
2+ import Validation , { IdentifierPath } from '../Validation'
3+ import RuntimeTypeErrorItem from '../errorReporting/RuntimeTypeErrorItem'
4+
5+ export default class TypeReference < T > extends Type < T > {
6+ typeName = 'TypeReference'
7+ readonly type : ( ) => Type < any >
8+
9+ constructor ( type : ( ) => Type < any > ) {
10+ super ( )
11+ this . type = type
12+ }
13+
14+ resolveType ( ) : Type < any > {
15+ return this . type ( ) . resolveType ( )
16+ }
17+
18+ * errors (
19+ validation : Validation ,
20+ path : IdentifierPath ,
21+ input : any
22+ ) : Iterable < RuntimeTypeErrorItem > {
23+ yield * this . type ( ) . errors ( validation , path , input )
24+ }
25+
26+ accepts ( input : any ) : input is T {
27+ return this . type ( ) . accepts ( input )
28+ }
29+
30+ get acceptsSomeCompositeTypes ( ) : boolean {
31+ return this . type ( ) . acceptsSomeCompositeTypes
32+ }
33+
34+ toString ( ) : string {
35+ return this . type ( ) . toString ( )
36+ }
37+ }
Original file line number Diff line number Diff line change 1+ import * as t from '../src'
2+ import { expect } from 'chai'
3+
4+ describe ( `t.opaque` , function ( ) {
5+ const DateString : t . OpaqueType < any > = t . opaque ( ( ) => t . string ( ) )
6+
7+ it ( `works` , function ( ) {
8+ DateString . assert ( 'foo' )
9+ expect ( DateString . accepts ( 'foo' ) ) . to . be . true
10+ } )
11+ } )
You can’t perform that action at this time.
0 commit comments