import Literal from './Literal' ; import { resolveReferencedType } from '../utils/referenceTypes' ; import TypeLiteral from './TypeLiteral' ; import UnionType from './UnionType' ; import MantaStyle from '..' ; import { Annotation , Type } from '@manta-style/core' ; export default class IndexedAccessType extends Type { private readonly objectType : Type ; private readonly indexType : Type ; constructor ( objectType , indexType ) { super ( ) ; this . objectType = objectType ; this . indexType = indexType ; } public getProperty ( ) { const { type : objType } = resolveReferencedType ( this . objectType ) ; const { type : indexType } = resolveReferencedType ( this . indexType ) ; const indexName = indexType . deriveLiteral ( [ ] ) . mock ( ) ; if ( objType instanceof TypeLiteral ) { return objType . _getProperties ( ) . find ( ( property ) => property . name === indexName ) ; } } private getObjectIndexTypes ( parentAnnotations = [ ] ) { const { objectType : maybeReferencedObjectType , indexType : maybeReferencedIndexType , } = this ; const objectType = resolveReferencedType ( maybeReferencedObjectType ) . type . deriveLiteral ( parentAnnotations ) ; const { type : indexType } = resolveReferencedType ( maybeReferencedIndexType ) ; return { objectType , indexType } ; } public deriveLiteral ( parentAnnotations ) { const { objectType , indexType } = this . getObjectIndexTypes ( ) ; if ( objectType instanceof TypeLiteral ) { if ( indexType instanceof Literal ) { return indexedAccessTypeLiteral ( objectType , indexType ) ; } else if ( indexType instanceof UnionType ) { const indexTypes = indexType . derivePreservedUnionLiteral ( [ ] ) . getTypes ( ) ; return new UnionType ( indexTypes . map ( ( indType ) => indexedAccessTypeLiteral ( objectType , indType ) ) ) ; } else { return new Literal ( 'Unimplemented' ) ; } } else { return objectType . deriveLiteral ( parentAnnotations ) ; } } public validate ( value ) { const { objectType , indexType } = this . getObjectIndexTypes ( ) ; if ( objectType instanceof TypeLiteral ) { if ( indexType instanceof Literal ) { return indexedAccessTypeLiteral ( objectType , indexType ) . validate ( value ) ; } else if ( indexType instanceof UnionType ) { const indexTypes = indexType . derivePreservedUnionLiteral ( [ ] ) . getTypes ( ) ; return new UnionType ( indexTypes . map ( ( indType ) => indexedAccessTypeLiteral ( objectType , indType ) ) ) . validate ( value ) ; } else { throw Error ( 'Unimplemented' ) ; } } else { return objectType . validate ( value ) ; } } public format ( value ) { const { objectType , indexType } = this . getObjectIndexTypes ( ) ; if ( objectType instanceof TypeLiteral ) { if ( indexType instanceof Literal ) { return indexedAccessTypeLiteral ( objectType , indexType ) . format ( value ) ; } else if ( indexType instanceof UnionType ) { const indexTypes = indexType . derivePreservedUnionLiteral ( [ ] ) . getTypes ( ) ; return new UnionType ( indexTypes . map ( ( indType ) => indexedAccessTypeLiteral ( objectType , indType ) ) ) . format ( value ) ; } else { throw Error ( 'Unimplemented' ) ; } } else { return objectType . format ( value ) ; } } } function indexedAccessTypeLiteral ( objectType , indexType ) { const key = indexType . mock ( ) ; const foundType = objectType . _getProperties ( ) . find ( ( item ) => item . name === key ) ; if ( foundType ) { return foundType . questionMark ? new UnionType ( [ foundType . type , MantaStyle . UndefinedKeyword ] ) : foundType . type ; } else { return MantaStyle . NeverKeyword ; } }