Skip to content

Commit 6facbf1

Browse files
Merge pull request #10403 from Microsoft/completionsForNullableObjects
Fix completions for nullable objects
2 parents f57b0fb + c1e70c9 commit 6facbf1

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

src/services/services.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3789,7 +3789,11 @@ namespace ts {
37893789
// other than those within the declared type.
37903790
isNewIdentifierLocation = true;
37913791

3792+
// If the object literal is being assigned to something of type 'null | { hello: string }',
3793+
// it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible.
37923794
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
3795+
typeForObject = typeForObject && typeForObject.getNonNullableType();
3796+
37933797
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
37943798
}
37953799
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
@@ -3801,7 +3805,7 @@ namespace ts {
38013805
// We don't want to complete using the type acquired by the shape
38023806
// of the binding pattern; we are only interested in types acquired
38033807
// through type declaration or inference.
3804-
// Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed -
3808+
// Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
38053809
// type of parameter will flow in from the contextual type of the function
38063810
let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type);
38073811
if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////interface Thing {
5+
//// hello: number;
6+
//// world: string;
7+
////}
8+
////
9+
////declare function funcA(x : Thing): void;
10+
////declare function funcB(x?: Thing): void;
11+
////declare function funcC(x : Thing | null): void;
12+
////declare function funcD(x : Thing | undefined): void;
13+
////declare function funcE(x : Thing | null | undefined): void;
14+
////declare function funcF(x?: Thing | null | undefined): void;
15+
////
16+
////funcA({ /*A*/ });
17+
////funcB({ /*B*/ });
18+
////funcC({ /*C*/ });
19+
////funcD({ /*D*/ });
20+
////funcE({ /*E*/ });
21+
////funcF({ /*F*/ });
22+
23+
24+
for (const marker of test.markers()) {
25+
goTo.position(marker.position);
26+
verify.completionListContains("hello");
27+
verify.completionListContains("world");
28+
}

0 commit comments

Comments
 (0)