import { GenericTypeAnnotation , TSIndexedAccessType , TSTypeLiteral , TSTypeOperator , TSTypeParameterInstantiation , TSTypeQuery , TSTypeReference , identifier , isGenericTypeAnnotation , isIdentifier , isTSObjectKeyword , isTSPropertySignature , isTSTypeLiteral , isTSTypeQuery , isTSTypeReference , isTypeAnnotation , stringLiteral , tsIndexedAccessType , tsLiteralType , tsTypeOperator , tsTypeParameterInstantiation , tsTypeQuery , tsTypeReference , tsUnionType , } from '@babel/types' ; import { NodePath } from '@babel/traverse' ; import { UnexpectedError } from '../../util/error' ; import { convertIdentifier } from './identifier' ; type UtilConvertor < R > = ( typeParameters : TSTypeParameterInstantiation ) => R ; export const convertCallUtility = typeParameters => tsTypeReference ( identifier ( 'ReturnType' ) , typeParameters ) ; export function convertClassUtil ( typeParameters , path ) { const typeParam = typeParameters . params [ 0 ] ; if ( isTSTypeReference ( typeParam ) ) { return tsTypeQuery ( typeParam . typeName ) ; } if ( isTSTypeQuery ( typeParam ) && isIdentifier ( typeParam . exprName ) ) { const binding = path . scope . getBinding ( typeParam . exprName . name ) ; if ( binding && isTypeAnnotation ( binding . identifier . typeAnnotation ) ) { const flowType = binding . identifier . typeAnnotation . typeAnnotation ; if ( isGenericTypeAnnotation ( flowType ) ) { return tsTypeQuery ( convertIdentifier ( flowType . id ) ) ; } } } throw new UnexpectedError ( `Unknown type parameter for Class<T> utility: ${ typeParam . type }.` ) ; } export const convertDiffUtil = typeParameters => { const secondParam = typeParameters . params [ 1 ] ; if ( isTSTypeReference ( secondParam ) && isIdentifier ( secondParam . typeName ) ) { secondParam . typeName . name = `keyof ${ secondParam . typeName . name }` ; } if ( isTSTypeLiteral ( secondParam ) || isTSObjectKeyword ( secondParam ) ) { const typeOperator = tsTypeOperator ( secondParam ) ; typeOperator . operator = 'keyof' ; typeParameters . params [ 1 ] = typeOperator ; } return tsTypeReference ( identifier ( 'Omit' ) , typeParameters ) ; } ; export const convertElementTypeUtil = typeParameters => tsIndexedAccessType ( typeParameters . params [ 0 ] , typeParameters . params [ 1 ] ) ; export const convertExactUtil = typeParameters => { const typeParam = typeParameters . params [ 0 ] ; if ( isTSTypeReference ( typeParam ) || isTSTypeLiteral ( typeParam ) ) { return typeParam ; } throw new UnexpectedError ( `Unexpected type parameter for $Exact<T>: ${ typeParam . type }` ) ; } ; export const convertKeysUtil = typeParameters => { const typeOperator = tsTypeOperator ( typeParameters . params [ 0 ] ) ; typeOperator . operator = 'keyof' ; return typeOperator ; } ; export const convertNonMaybeTypeUtil = typeParameters => tsTypeReference ( identifier ( 'NonNullable' ) , typeParameters ) ; export const convertPropertyTypeUtil = typeParameters => tsIndexedAccessType ( typeParameters . params [ 0 ] , typeParameters . params [ 1 ] ) ; export const convertReadOnlyArrayUtil = typeParameters => tsTypeReference ( identifier ( 'ReadonlyArray' ) , typeParameters ) ; export const convertRestUtil = typeParameters => { const [ typeName , restArg ] = typeParameters . params ; const omitArg = isTSTypeLiteral ( restArg ) ? tsUnionType ( restArg . members . map ( typeElem => { return tsLiteralType ( stringLiteral ( isTSPropertySignature ( typeElem ) && isIdentifier ( typeElem . key ) ? typeElem . key . name : '' ) ) ; } ) ) : restArg ; return tsTypeReference ( identifier ( 'Omit' ) , tsTypeParameterInstantiation ( [ typeName , omitArg ] ) ) ; } ; export const convertShapeUtil = typeParameters => tsTypeReference ( identifier ( 'Partial' ) , typeParameters ) ; export const convertReadOnlyUtil = typeParameters => tsTypeReference ( identifier ( 'Readonly' ) , typeParameters ) ;