Skip to content

Commit 6a996ac

Browse files
authored
Additional fix to issue #50509 (#54423)
1 parent d95caa5 commit 6a996ac

File tree

3 files changed

+200
-13
lines changed

3 files changed

+200
-13
lines changed

src/compiler/checker.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28698,6 +28698,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2869828698
});
2869928699
}
2870028700

28701+
function getThisTypeOfObjectLiteralFromContextualType(containingLiteral: ObjectLiteralExpression, contextualType: Type | undefined) {
28702+
let literal = containingLiteral;
28703+
let type = contextualType;
28704+
while (type) {
28705+
const thisType = getThisTypeFromContextualType(type);
28706+
if (thisType) {
28707+
return thisType;
28708+
}
28709+
if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
28710+
break;
28711+
}
28712+
literal = literal.parent.parent as ObjectLiteralExpression;
28713+
type = getApparentTypeOfContextualType(literal, /*contextFlags*/ undefined);
28714+
}
28715+
}
28716+
2870128717
function getContextualThisParameterType(func: SignatureDeclaration): Type | undefined {
2870228718
if (func.kind === SyntaxKind.ArrowFunction) {
2870328719
return undefined;
@@ -28719,18 +28735,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2871928735
// that includes a ThisType<T>. If so, T is the contextual type for 'this'. We continue looking in
2872028736
// any directly enclosing object literals.
2872128737
const contextualType = getApparentTypeOfContextualType(containingLiteral, /*contextFlags*/ undefined);
28722-
let literal = containingLiteral;
28723-
let type = contextualType;
28724-
while (type) {
28725-
const thisType = getThisTypeFromContextualType(type);
28726-
if (thisType) {
28727-
return instantiateType(thisType, getMapperFromContext(getInferenceContext(containingLiteral)));
28728-
}
28729-
if (literal.parent.kind !== SyntaxKind.PropertyAssignment) {
28730-
break;
28731-
}
28732-
literal = literal.parent.parent as ObjectLiteralExpression;
28733-
type = getApparentTypeOfContextualType(literal, /*contextFlags*/ undefined);
28738+
const thisType = getThisTypeOfObjectLiteralFromContextualType(containingLiteral, contextualType);
28739+
if (thisType) {
28740+
return instantiateType(thisType, getMapperFromContext(getInferenceContext(containingLiteral)));
2873428741
}
2873528742
// There was no contextual ThisType<T> for the containing object literal, so the contextual type
2873628743
// for 'this' is the non-null form of the contextual type for the containing object literal or
@@ -45455,7 +45462,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4545545462
const containingLiteral = getContainingObjectLiteral(container);
4545645463
if (containingLiteral) {
4545745464
const contextualType = getApparentTypeOfContextualType(containingLiteral, /*contextFlags*/ undefined);
45458-
const type = contextualType && getThisTypeFromContextualType(contextualType);
45465+
const type = getThisTypeOfObjectLiteralFromContextualType(containingLiteral, contextualType);
4545945466
return type && !isTypeAny(type);
4546045467
}
4546145468
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// === findAllReferences ===
2+
// === /tests/cases/fourslash/infer.d.ts ===
3+
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|{| isWriteAccess: true |}x|]: number|> }>): void;
4+
5+
// === /tests/cases/fourslash/a.js ===
6+
// import { infer } from "./infer";
7+
// infer({
8+
// m: {
9+
// initData() {
10+
// <|this.[|{| isWriteAccess: true |}x|] = 1;|>
11+
// this./*FIND ALL REFS*/[|x|];
12+
// },
13+
// }
14+
// });
15+
16+
// === /tests/cases/fourslash/b.ts ===
17+
// import { infer } from "./infer";
18+
// infer({
19+
// m: {
20+
// initData() {
21+
// this.[|{| isWriteAccess: true |}x|] = 1;
22+
// this.[|x|];
23+
// },
24+
// }
25+
// });
26+
27+
// === Definitions ===
28+
// === /tests/cases/fourslash/infer.d.ts ===
29+
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|x|]: number|> }>): void;
30+
31+
// === Details ===
32+
[
33+
{
34+
"containerKind": "",
35+
"containerName": "",
36+
"kind": "property",
37+
"name": "(property) x: number",
38+
"displayParts": [
39+
{
40+
"text": "(",
41+
"kind": "punctuation"
42+
},
43+
{
44+
"text": "property",
45+
"kind": "text"
46+
},
47+
{
48+
"text": ")",
49+
"kind": "punctuation"
50+
},
51+
{
52+
"text": " ",
53+
"kind": "space"
54+
},
55+
{
56+
"text": "x",
57+
"kind": "propertyName"
58+
},
59+
{
60+
"text": ":",
61+
"kind": "punctuation"
62+
},
63+
{
64+
"text": " ",
65+
"kind": "space"
66+
},
67+
{
68+
"text": "number",
69+
"kind": "keyword"
70+
}
71+
]
72+
}
73+
]
74+
75+
76+
77+
// === findAllReferences ===
78+
// === /tests/cases/fourslash/infer.d.ts ===
79+
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|{| isWriteAccess: true |}x|]: number|> }>): void;
80+
81+
// === /tests/cases/fourslash/a.js ===
82+
// import { infer } from "./infer";
83+
// infer({
84+
// m: {
85+
// initData() {
86+
// <|this.[|{| isWriteAccess: true |}x|] = 1;|>
87+
// this.[|x|];
88+
// },
89+
// }
90+
// });
91+
92+
// === /tests/cases/fourslash/b.ts ===
93+
// import { infer } from "./infer";
94+
// infer({
95+
// m: {
96+
// initData() {
97+
// this.[|{| isWriteAccess: true |}x|] = 1;
98+
// this./*FIND ALL REFS*/[|x|];
99+
// },
100+
// }
101+
// });
102+
103+
// === Definitions ===
104+
// === /tests/cases/fourslash/infer.d.ts ===
105+
// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ <|[|x|]: number|> }>): void;
106+
107+
// === Details ===
108+
[
109+
{
110+
"containerKind": "",
111+
"containerName": "",
112+
"kind": "property",
113+
"name": "(property) x: number",
114+
"displayParts": [
115+
{
116+
"text": "(",
117+
"kind": "punctuation"
118+
},
119+
{
120+
"text": "property",
121+
"kind": "text"
122+
},
123+
{
124+
"text": ")",
125+
"kind": "punctuation"
126+
},
127+
{
128+
"text": " ",
129+
"kind": "space"
130+
},
131+
{
132+
"text": "x",
133+
"kind": "propertyName"
134+
},
135+
{
136+
"text": ":",
137+
"kind": "punctuation"
138+
},
139+
{
140+
"text": " ",
141+
"kind": "space"
142+
},
143+
{
144+
"text": "number",
145+
"kind": "keyword"
146+
}
147+
]
148+
}
149+
]
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowJs: true
4+
// @noImplicitThis: true
5+
6+
// @Filename: infer.d.ts
7+
//// export declare function infer(o: { m: Record<string, Function> } & ThisType<{ x: number }>): void;
8+
9+
// @Filename: a.js
10+
//// import { infer } from "./infer";
11+
//// infer({
12+
//// m: {
13+
//// initData() {
14+
//// this.x = 1;
15+
//// this./*1*/x;
16+
//// },
17+
//// }
18+
//// });
19+
20+
// @Filename: b.ts
21+
//// import { infer } from "./infer";
22+
//// infer({
23+
//// m: {
24+
//// initData() {
25+
//// this.x = 1;
26+
//// this./*2*/x;
27+
//// },
28+
//// }
29+
//// });
30+
31+
verify.baselineFindAllReferences("1", "2");

0 commit comments

Comments
 (0)