UNPKG

mezzanine

Version:

Fantasy land union types with pattern matching

115 lines (101 loc) 2.95 kB
//@flow 'use strict' import { is } from 'ramda' type NativeType = typeof Number | typeof String | typeof Boolean | typeof Object | typeof Array | typeof Function | typeof RegExp | typeof Symbol type Pred = (input: *, dataKey: ?string) => boolean interface Model { +ಠ_ಠ: Symbol, +keys: string[], is(val: *): boolean, // [key: string]: *, } type Proof = NativeType | Pred | Model | { +[key: string]: Model | NativeType | Pred } // interface ModelCheck { // () // } const proofCase = { native: (rule: NativeType | mixed): boolean %checks => rule === Number || rule === String || rule === Boolean || rule === Object || rule === Array || rule === Function || rule === RegExp || rule === Symbol, func : (rule: mixed): boolean %checks => typeof rule === 'function', model: (rule: *): boolean %checks => ( typeof rule === 'function' && rule.ಠ_ಠ !== undefined && typeof rule.is === 'function'), obj: (rule: mixed): boolean %checks => typeof rule === 'object', } /** * * @deprecated */ export const isSingleProof = (proof: *): boolean %checks => // proofCase.model(proof) proofCase.native(proof) || proofCase.func(proof) export const isSingleAlike = (proof: *): boolean %checks => typeof proof === 'object' && Object.keys(proof).length === 1 && Object.keys(proof)[0] === 'value' export const validateMono = (proof: Proof) => (data: mixed, dataKey: ?string) => { if (proof === Number || proof === String || proof === Boolean || proof === Object || proof === Array || proof === Function || proof === RegExp || proof === Symbol) return is(proof, data) else if (typeof proof === 'function' && proof.ಠ_ಠ !== undefined && typeof proof.is === 'function') return proof.is(data) else if (typeof proof === 'function') return proof(data, dataKey) return false } const canAccessKeys = (data: *): %checks => typeof data === 'object' || proofCase.model(data) function validate(proof: Proof, data: mixed, dataKey: ?string): boolean { if (proofCase.native(proof)) return is(proof, data) //$FlowIssue if (proofCase.model(proof)) return proof.is(data) if (typeof proof === 'function') return proof(data, dataKey) if (proof == null) return false if (data == null) return false if (proofCase.obj(proof) && (canAccessKeys(data))) { ((proof): {+[key: string]: Proof}) const tProof: {+[key: string]: Proof} = (proof: any) const typeKeys = Object.keys(tProof) if (typeKeys.length === 0) return true for (const typeKey of typeKeys) { const rule: Proof = tProof[typeKey] //$FlowIssue const property = data[typeKey] const result = validate(rule, property, typeKey) if (!result) return false } return true } return false } export default validate