Skip to content

Commit a738dfc

Browse files
authored
Fix noSelf in object literal methods (#1088)
* Fix noSelf in object literal methods * Add isObjectLiteralExpression check on parent This check is absent in the internal typescript method * Add more tests for PR Co-authored-by: Benjamin Ye <24237065+enjoydambience@users.noreply.github.com>
1 parent ab99a73 commit a738dfc

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

src/transformation/utils/function-context.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,25 @@ function getSignatureDeclarations(
113113
): ts.SignatureDeclaration[] {
114114
return signatures.flatMap(signature => {
115115
const signatureDeclaration = signature.getDeclaration();
116+
let inferredType: ts.Type | undefined;
116117
if (
118+
ts.isMethodDeclaration(signatureDeclaration) &&
119+
ts.isObjectLiteralExpression(signatureDeclaration.parent) &&
120+
!getExplicitThisParameter(signatureDeclaration)
121+
) {
122+
inferredType = context.checker.getContextualTypeForObjectLiteralElement(signatureDeclaration);
123+
} else if (
117124
(ts.isFunctionExpression(signatureDeclaration) || ts.isArrowFunction(signatureDeclaration)) &&
118125
!getExplicitThisParameter(signatureDeclaration)
119126
) {
120127
// Infer type of function expressions/arrow functions
121-
const inferredType = inferAssignedType(context, signatureDeclaration);
122-
if (inferredType) {
123-
const inferredSignatures = getAllCallSignatures(inferredType);
124-
if (inferredSignatures.length > 0) {
125-
return inferredSignatures.map(s => s.getDeclaration());
126-
}
128+
inferredType = inferAssignedType(context, signatureDeclaration);
129+
}
130+
131+
if (inferredType) {
132+
const inferredSignatures = getAllCallSignatures(inferredType);
133+
if (inferredSignatures.length > 0) {
134+
return inferredSignatures.map(s => s.getDeclaration());
127135
}
128136
}
129137

src/typescript-internal.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ declare module "typescript" {
2626

2727
interface TypeChecker {
2828
getElementTypeOfArrayType(type: Type): Type | undefined;
29+
getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike): Type | undefined;
2930
}
3031
}

test/unit/objectLiteral.spec.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,66 @@ test.each(['{x: "foobar"}.x', '{x: "foobar"}["x"]', '{x: () => "foobar"}.x()', '
6363
util.testExpression(expression).expectToMatchJsResult();
6464
}
6565
);
66+
67+
describe("noSelf in functions", () => {
68+
test("Explicit this: void parameter", () => {
69+
// language=TypeScript
70+
util.testFunction`
71+
const obj: Record<string, (this: void, arg: string) => string> = {
72+
method(a) {
73+
return a;
74+
},
75+
func: function(a) {
76+
return a;
77+
},
78+
arrow: (a) => {
79+
return a;
80+
}
81+
};
82+
return [obj.method("a") ?? "nil", obj.func("b") ?? "nil", obj.arrow("c") ?? "nil"];
83+
`.expectToMatchJsResult();
84+
});
85+
86+
test("No self annotation", () => {
87+
// language=TypeScript
88+
util.testFunction`
89+
const obj: Record<string, /** @noSelf */(arg: string) => string> = {
90+
method(a) {
91+
return a;
92+
},
93+
func: function(a) {
94+
return a;
95+
},
96+
arrow: (a) => {
97+
return a;
98+
}
99+
};
100+
return [obj.method("a") ?? "nil", obj.func("b") ?? "nil", obj.arrow("c") ?? "nil"];
101+
`.expectToMatchJsResult();
102+
});
103+
104+
test("individual function types", () => {
105+
// language=TypeScript
106+
util.testFunction`
107+
interface FunctionContainer {
108+
method: (this: void, a: string) => string
109+
func: (this: void, a: string) => string
110+
arrow: (this: void, a: string) => string
111+
}
112+
113+
const obj: FunctionContainer = {
114+
method(a) {
115+
return a
116+
},
117+
func: function(a) {
118+
return a
119+
},
120+
arrow: (a) => {
121+
return a
122+
}
123+
}
124+
125+
return [obj.method("a") ?? "nil", obj.func("b") ?? "nil", obj.arrow("c") ?? "nil"];
126+
`.expectToMatchJsResult();
127+
});
128+
});

0 commit comments

Comments
 (0)