@@ -23,6 +23,7 @@ import {
2323 flatMap ,
2424 FunctionDeclaration ,
2525 FunctionExpression ,
26+ GenericType ,
2627 GetAccessorDeclaration ,
2728 getAllAccessorDeclarations ,
2829 getCheckFlags ,
@@ -59,6 +60,8 @@ import {
5960 isSetAccessorDeclaration ,
6061 isStringLiteral ,
6162 isTypeNode ,
63+ isTypeReferenceNode ,
64+ TypeReferenceNode ,
6265 isTypeUsableAsPropertyName ,
6366 isYieldExpression ,
6467 LanguageServiceHost ,
@@ -595,7 +598,15 @@ function createTypeParameterName(index: number) {
595598
596599/** @internal */
597600export function typeToAutoImportableTypeNode ( checker : TypeChecker , importAdder : ImportAdder , type : Type , contextNode : Node | undefined , scriptTarget : ScriptTarget , flags ?: NodeBuilderFlags , internalFlags ?: InternalNodeBuilderFlags , tracker ?: SymbolTracker ) : TypeNode | undefined {
598- let typeNode = checker . typeToTypeNode ( type , contextNode , flags , internalFlags , tracker ) ;
601+ const typeNode = checker . typeToTypeNode ( type , contextNode , flags , internalFlags , tracker ) ;
602+ if ( ! typeNode ) {
603+ return undefined ;
604+ }
605+ return typeNodeToAutoImportableTypeNode ( typeNode , importAdder , scriptTarget ) ;
606+ }
607+
608+ /** @internal */
609+ export function typeNodeToAutoImportableTypeNode ( typeNode : TypeNode , importAdder : ImportAdder , scriptTarget : ScriptTarget ) : TypeNode | undefined {
599610 if ( typeNode && isImportTypeNode ( typeNode ) ) {
600611 const importableReference = tryGetAutoImportableReferenceFromTypeNode ( typeNode , scriptTarget ) ;
601612 if ( importableReference ) {
@@ -608,6 +619,43 @@ export function typeToAutoImportableTypeNode(checker: TypeChecker, importAdder:
608619 return getSynthesizedDeepClone ( typeNode ) ;
609620}
610621
622+ function endOfRequiredTypeParameters ( checker : TypeChecker , type : GenericType , fullTypeArguments : readonly Type [ ] ) : number {
623+ if ( fullTypeArguments !== type . typeArguments ! ) {
624+ throw new Error ( 'fullTypeArguments should be set' )
625+ }
626+ const target = type . target ;
627+ next_cutoff: for ( let cutoff = 0 ; cutoff < fullTypeArguments . length ; cutoff ++ ) {
628+ const typeArguments = fullTypeArguments . slice ( 0 , cutoff ) ;
629+ const filledIn = checker . fillMissingTypeArguments ( typeArguments , target . typeParameters , cutoff , /*isJavaScriptImplicitAny*/ false ) ;
630+ for ( let i = 0 ; i < filledIn . length ; i ++ ) {
631+ // If they don't match, then we haven't yet reached the right cutoff
632+ if ( filledIn [ i ] !== fullTypeArguments [ i ] ) continue next_cutoff;
633+ }
634+ return cutoff ;
635+ }
636+ // If we make it all the way here, all the type arguments are required.
637+ return fullTypeArguments . length ;
638+ }
639+
640+ export function typeToMinimizedReferenceType ( checker : TypeChecker , type : Type , contextNode : Node | undefined , flags ?: NodeBuilderFlags , internalFlags ?: InternalNodeBuilderFlags , tracker ?: SymbolTracker ) : TypeNode | undefined {
641+ const typeNode = checker . typeToTypeNode ( type , contextNode , flags , internalFlags , tracker ) ;
642+ if ( ! typeNode ) {
643+ return undefined ;
644+ }
645+ if ( isTypeReferenceNode ( typeNode ) ) {
646+ const genericType = type as GenericType ;
647+ if ( genericType . typeArguments ) {
648+ const cutoff = endOfRequiredTypeParameters ( checker , genericType , genericType . typeArguments ) ;
649+ if ( cutoff !== undefined && typeNode . typeArguments ) {
650+ // Looks like the wrong way to do this. What APIs should I use here?
651+ ( typeNode as any ) . typeArguments = typeNode . typeArguments . slice ( 0 , cutoff ) ;
652+ }
653+ }
654+
655+ }
656+ return typeNode ;
657+ }
658+
611659/** @internal */
612660export function typePredicateToAutoImportableTypeNode ( checker : TypeChecker , importAdder : ImportAdder , typePredicate : TypePredicate , contextNode : Node | undefined , scriptTarget : ScriptTarget , flags ?: NodeBuilderFlags , internalFlags ?: InternalNodeBuilderFlags , tracker ?: SymbolTracker ) : TypeNode | undefined {
613661 let typePredicateNode = checker . typePredicateToTypePredicateNode ( typePredicate , contextNode , flags , internalFlags , tracker ) ;
0 commit comments