Skip to content

Commit 2b2d6ce

Browse files
authored
Improve references search and quick info on properties with type errors within nullable contextual types (#61383)
1 parent 6fd2874 commit 2b2d6ce

File tree

5 files changed

+176
-0
lines changed

5 files changed

+176
-0
lines changed

src/services/services.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,6 +3575,7 @@ function getSymbolAtLocationForQuickInfo(node: Node, checker: TypeChecker): Symb
35753575
* @internal
35763576
*/
35773577
export function getPropertySymbolsFromContextualType(node: ObjectLiteralElementWithName, checker: TypeChecker, contextualType: Type, unionSymbolOk: boolean): readonly Symbol[] {
3578+
contextualType = contextualType.getNonNullableType();
35783579
const name = getNameFromPropertyName(node.name);
35793580
if (!name) return emptyArray;
35803581
if (!contextualType.isUnion()) {
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// === findAllReferences ===
2+
// === /tests/cases/fourslash/findAllRefsFromContextualUnionType1.ts ===
3+
// function test1(arg: { <|[|prop|]: "foo"|> }) {}
4+
// test1({ /*FIND ALL REFS*/<|[|{| isWriteAccess: true, isDefinition: true |}prop|]: "bar"|> });
5+
//
6+
// function test2(arg: { prop: "foo" } | undefined) {}
7+
// test2({ prop: "bar" });
8+
9+
// === Definitions ===
10+
// === /tests/cases/fourslash/findAllRefsFromContextualUnionType1.ts ===
11+
// function test1(arg: { <|[|prop|]: "foo"|> }) {}
12+
// test1({ /*FIND ALL REFS*/prop: "bar" });
13+
//
14+
// function test2(arg: { prop: "foo" } | undefined) {}
15+
// test2({ prop: "bar" });
16+
17+
// === Details ===
18+
[
19+
{
20+
"containerKind": "",
21+
"containerName": "",
22+
"kind": "property",
23+
"name": "(property) prop: \"foo\"",
24+
"displayParts": [
25+
{
26+
"text": "(",
27+
"kind": "punctuation"
28+
},
29+
{
30+
"text": "property",
31+
"kind": "text"
32+
},
33+
{
34+
"text": ")",
35+
"kind": "punctuation"
36+
},
37+
{
38+
"text": " ",
39+
"kind": "space"
40+
},
41+
{
42+
"text": "prop",
43+
"kind": "propertyName"
44+
},
45+
{
46+
"text": ":",
47+
"kind": "punctuation"
48+
},
49+
{
50+
"text": " ",
51+
"kind": "space"
52+
},
53+
{
54+
"text": "\"foo\"",
55+
"kind": "stringLiteral"
56+
}
57+
]
58+
}
59+
]
60+
61+
62+
63+
// === findAllReferences ===
64+
// === /tests/cases/fourslash/findAllRefsFromContextualUnionType1.ts ===
65+
// function test1(arg: { prop: "foo" }) {}
66+
// test1({ prop: "bar" });
67+
//
68+
// function test2(arg: { <|[|prop|]: "foo"|> } | undefined) {}
69+
// test2({ /*FIND ALL REFS*/<|[|{| isWriteAccess: true, isDefinition: true |}prop|]: "bar"|> });
70+
71+
// === Definitions ===
72+
// === /tests/cases/fourslash/findAllRefsFromContextualUnionType1.ts ===
73+
// function test1(arg: { prop: "foo" }) {}
74+
// test1({ prop: "bar" });
75+
//
76+
// function test2(arg: { <|[|prop|]: "foo"|> } | undefined) {}
77+
// test2({ /*FIND ALL REFS*/prop: "bar" });
78+
79+
// === Details ===
80+
[
81+
{
82+
"containerKind": "",
83+
"containerName": "",
84+
"kind": "property",
85+
"name": "(property) prop: \"foo\"",
86+
"displayParts": [
87+
{
88+
"text": "(",
89+
"kind": "punctuation"
90+
},
91+
{
92+
"text": "property",
93+
"kind": "text"
94+
},
95+
{
96+
"text": ")",
97+
"kind": "punctuation"
98+
},
99+
{
100+
"text": " ",
101+
"kind": "space"
102+
},
103+
{
104+
"text": "prop",
105+
"kind": "propertyName"
106+
},
107+
{
108+
"text": ":",
109+
"kind": "punctuation"
110+
},
111+
{
112+
"text": " ",
113+
"kind": "space"
114+
},
115+
{
116+
"text": "\"foo\"",
117+
"kind": "stringLiteral"
118+
}
119+
]
120+
}
121+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @strict: true
4+
//// function test1(arg: { prop: "foo" }) {}
5+
//// test1({ /*1*/prop: "bar" });
6+
////
7+
//// function test2(arg: { prop: "foo" } | undefined) {}
8+
//// test2({ /*2*/prop: "bar" });
9+
10+
verify.baselineFindAllReferences("1", "2");
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @strict: true
4+
//// function test1(arg: { prop: "foo" }) {}
5+
//// test1({ /*1*/prop: "bar" });
6+
////
7+
//// function test2(arg: { prop: "foo" } | undefined) {}
8+
//// test2({ /*2*/prop: "bar" });
9+
10+
verify.quickInfoAt("1", '(property) prop: "foo"');
11+
verify.quickInfoAt("2", '(property) prop: "foo"');
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// https://github.com/microsoft/TypeScript/issues/61382
4+
5+
// @strict: true
6+
//// declare const foo1: <D extends Foo1<D>>(definition: D) => D;
7+
////
8+
//// type Foo1<D, Bar = Prop<D, "bar">> = {
9+
//// bar: {
10+
//// [K in keyof Bar]: Bar[K] extends boolean
11+
//// ? Bar[K]
12+
//// : "Error: bar should be boolean";
13+
//// };
14+
//// };
15+
////
16+
//// declare const foo2: <D extends Foo2<D>>(definition: D) => D;
17+
////
18+
//// type Foo2<D, Bar = Prop<D, "bar">> = {
19+
//// bar?: {
20+
//// [K in keyof Bar]: Bar[K] extends boolean
21+
//// ? Bar[K]
22+
//// : "Error: bar should be boolean";
23+
//// };
24+
//// };
25+
////
26+
//// type Prop<T, K> = K extends keyof T ? T[K] : never;
27+
////
28+
//// foo1({ bar: { /*1*/X: "test" } });
29+
////
30+
//// foo2({ bar: { /*2*/X: "test" } });
31+
32+
verify.quickInfoAt("1", '(property) X: "Error: bar should be boolean"');
33+
verify.quickInfoAt("2", '(property) X: "Error: bar should be boolean"');

0 commit comments

Comments
 (0)