import { resolveReferencedType } from './referenceTypes' ; import Literal from '../types/Literal' ; import AnyKeyword from '../types/AnyKeyword' ; import NumberKeyword from '../types/NumberKeyword' ; import StringKeyword from '../types/StringKeyword' ; import BooleanKeyword from '../types/BooleanKeyword' ; import UnionType from '../types/UnionType' ; import TypeLiteral from '../types/TypeLiteral' ; import IntersectionType from '../types/IntersectionType' ; import { Type } from '@manta-style/core' ; export function isAssignable ( typeS , typeT ) { const { type : S } = resolveReferencedType ( typeS ) ; const { type : T } = resolveReferencedType ( typeT ) ; if ( Object . getPrototypeOf ( S ) === Object . getPrototypeOf ( T ) ) { if ( S instanceof Literal && T instanceof Literal ) { return S . mock ( ) === T . mock ( ) ; } return true ; } else if ( S instanceof AnyKeyword || T instanceof AnyKeyword ) { return true ; } else if ( S instanceof Literal && typeof S . mock ( ) === 'number' && T instanceof NumberKeyword ) { return true ; } else if ( S instanceof Literal && typeof S . mock ( ) === 'string' && T instanceof StringKeyword ) { return true ; } else if ( S instanceof Literal && typeof S . mock ( ) === 'boolean' && T instanceof BooleanKeyword ) { return true ; } else if ( S instanceof UnionType ) { return S . getTypes ( ) . every ( ( type ) => isAssignable ( type , T ) ) ; } else if ( S instanceof IntersectionType ) { return S . getTypes ( ) . some ( ( type ) => isAssignable ( type , T ) ) ; } else if ( T instanceof UnionType ) { return T . getTypes ( ) . some ( ( type ) => isAssignable ( S , type ) ) ; } else if ( T instanceof IntersectionType ) { return T . getTypes ( ) . every ( ( type ) => isAssignable ( S , type ) ) ; } else if ( S instanceof TypeLiteral && T instanceof TypeLiteral ) { const SProperties = S . _getProperties ( ) ; const TProperties = T . _getProperties ( ) ; return TProperties . every ( ( M ) => { const N = SProperties . find ( ( property ) => property . name === M . name ) ; if ( N && isAssignable ( N . type , M . type ) && ! M . questionMark && ! N . questionMark ) { return true ; } if ( M . questionMark && ! N ) { return true ; } return false ; } ) ; } return false ; }