import { sample } from 'lodash-es' ; import NeverKeyword from './NeverKeyword' ; import { resolveReferencedType } from '../utils/referenceTypes' ; import { Annotation , Type } from '@manta-style/core' ; import { throwUnableToFormat } from '../utils/errorReporting' ; export default class UnionType extends Type { private readonly types : Type [ ] = [ ] ; private chosenType ? : Type ; constructor ( types , chosenType ? ) { super ( ) ; this . types = types ; this . chosenType = chosenType ; } public deriveLiteral ( parentAnnotations ) { const { chosenType } = this ; if ( chosenType ) { return chosenType ; } else { const { chosenType } = this . derivePreservedUnionLiteral ( parentAnnotations ) ; if ( chosenType ) { return chosenType ; } throw Error ( 'Something bad happens :(' ) ; } } public derivePreservedUnionLiteral ( parentAnnotations ) { const resolvedTypes = this . types . map ( ( type ) => resolveReferencedType ( type ) ) ; const derivedTypes = resolvedTypes . map ( ( item ) => item . type ) . filter ( ( type ) => ! ( type instanceof NeverKeyword ) ) . map ( ( type ) => type . deriveLiteral ( parentAnnotations ) ) ; const chosenType = sample ( derivedTypes ) ; return new UnionType ( derivedTypes , chosenType ) ; } public mock ( ) { const { chosenType } = this ; if ( chosenType ) { return chosenType . mock ( ) ; } throw Error ( 'Something bad happens :(' ) ; } public validate ( value ) { return this . types . some ( ( type ) => type . validate ( value ) ) ; } public format ( value ) { for ( const type of this . types ) { try { return type . format ( value ) ; } catch { } } const potentialExpectedValues = [ ] ; for ( const type of this . types ) { try { potentialExpectedValues . push ( type . mock ( ) ) ; } catch { } } throwUnableToFormat ( { typeName : 'UnionType' , reason : 'The input cannot be validated as any type in this UnionType. ' + 'Please check Expected Values for potentially expected values.' , inputValue : value , expectedValue : potentialExpectedValues , } ) ; } public getTypes ( ) { return this . types ; } }