@@ -1510,7 +1510,8 @@ namespace ts.Completions {
1510
1510
}
1511
1511
1512
1512
function tryGetGlobalSymbols ( ) : boolean {
1513
- const result : GlobalsSearch = tryGetObjectLikeCompletionSymbols ( )
1513
+ const result : GlobalsSearch = tryGetObjectTypeLiteralInTypeArgumentCompletionSymbols ( )
1514
+ || tryGetObjectLikeCompletionSymbols ( )
1514
1515
|| tryGetImportCompletionSymbols ( )
1515
1516
|| tryGetImportOrExportClauseCompletionSymbols ( )
1516
1517
|| tryGetLocalNamedExportCompletionSymbols ( )
@@ -1913,6 +1914,32 @@ namespace ts.Completions {
1913
1914
position === contextToken . end && ( ! ! contextToken . isUnterminated || isRegularExpressionLiteral ( contextToken ) ) ) ;
1914
1915
}
1915
1916
1917
+ function tryGetObjectTypeLiteralInTypeArgumentCompletionSymbols ( ) : GlobalsSearch | undefined {
1918
+ const typeLiteralNode = tryGetTypeLiteralNode ( contextToken ) ;
1919
+ if ( ! typeLiteralNode ) return GlobalsSearch . Continue ;
1920
+
1921
+ const intersectionTypeNode = isIntersectionTypeNode ( typeLiteralNode . parent ) ? typeLiteralNode . parent : undefined ;
1922
+ const containerTypeNode = intersectionTypeNode || typeLiteralNode ;
1923
+
1924
+ const containerExpectedType = getConstraintOfTypeArgumentProperty ( containerTypeNode , typeChecker ) ;
1925
+ if ( ! containerExpectedType ) return GlobalsSearch . Continue ;
1926
+
1927
+ const containerActualType = typeChecker . getTypeFromTypeNode ( containerTypeNode ) ;
1928
+
1929
+ const members = getPropertiesForCompletion ( containerExpectedType , typeChecker ) ;
1930
+ const existingMembers = getPropertiesForCompletion ( containerActualType , typeChecker ) ;
1931
+
1932
+ const existingMemberEscapedNames : Set < __String > = new Set ( ) ;
1933
+ existingMembers . forEach ( s => existingMemberEscapedNames . add ( s . escapedName ) ) ;
1934
+
1935
+ symbols = filter ( members , s => ! existingMemberEscapedNames . has ( s . escapedName ) ) ;
1936
+
1937
+ completionKind = CompletionKind . ObjectPropertyDeclaration ;
1938
+ isNewIdentifierLocation = true ;
1939
+
1940
+ return GlobalsSearch . Success ;
1941
+ }
1942
+
1916
1943
/**
1917
1944
* Aggregates relevant symbols for completion in object literals and object binding patterns.
1918
1945
* Relevant symbols are stored in the captured 'symbols' variable.
@@ -2859,6 +2886,49 @@ namespace ts.Completions {
2859
2886
}
2860
2887
}
2861
2888
2889
+ function tryGetTypeLiteralNode ( node : Node ) : TypeLiteralNode | undefined {
2890
+ if ( ! node ) return undefined ;
2891
+
2892
+ const parent = node . parent ;
2893
+
2894
+ switch ( node . kind ) {
2895
+ case SyntaxKind . OpenBraceToken :
2896
+ if ( isTypeLiteralNode ( parent ) ) {
2897
+ return parent ;
2898
+ }
2899
+ break ;
2900
+ case SyntaxKind . SemicolonToken :
2901
+ case SyntaxKind . CommaToken :
2902
+ case SyntaxKind . Identifier :
2903
+ if ( parent . kind === SyntaxKind . PropertySignature && isTypeLiteralNode ( parent . parent ) ) {
2904
+ return parent . parent ;
2905
+ }
2906
+ break ;
2907
+ }
2908
+
2909
+ return undefined ;
2910
+ }
2911
+
2912
+ function getConstraintOfTypeArgumentProperty ( node : Node , checker : TypeChecker ) : Type | undefined {
2913
+ if ( ! node ) return undefined ;
2914
+
2915
+ if ( isTypeNode ( node ) && isTypeReferenceType ( node . parent ) ) {
2916
+ return checker . getTypeArgumentConstraint ( node ) ;
2917
+ }
2918
+
2919
+ const t = getConstraintOfTypeArgumentProperty ( node . parent , checker ) ;
2920
+ if ( ! t ) return undefined ;
2921
+
2922
+ switch ( node . kind ) {
2923
+ case SyntaxKind . PropertySignature :
2924
+ return checker . getTypeOfPropertyOfContextualType ( t , node . symbol . escapedName ) ;
2925
+ case SyntaxKind . IntersectionType :
2926
+ case SyntaxKind . TypeLiteral :
2927
+ case SyntaxKind . UnionType :
2928
+ return t ;
2929
+ }
2930
+ }
2931
+
2862
2932
// TODO: GH#19856 Would like to return `node is Node & { parent: (ClassElement | TypeElement) & { parent: ObjectTypeDeclaration } }` but then compilation takes > 10 minutes
2863
2933
function isFromObjectTypeDeclaration ( node : Node ) : boolean {
2864
2934
return node . parent && isClassOrTypeElement ( node . parent ) && isObjectTypeDeclaration ( node . parent . parent ) ;
0 commit comments