Skip to content

Commit f88f029

Browse files
Merge pull request microsoft#4862 from Microsoft/contextuallyTypeMethodDeclarations
Contextually type method declaration parameters in object literals
2 parents cd390fd + 254af55 commit f88f029

13 files changed

+823
-7
lines changed

src/compiler/checker.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -6574,8 +6574,8 @@ namespace ts {
65746574

65756575
// Return contextual type of parameter or undefined if no contextual type is available
65766576
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
6577-
if (isFunctionExpressionOrArrowFunction(parameter.parent)) {
6578-
let func = <FunctionExpression>parameter.parent;
6577+
let func = parameter.parent;
6578+
if (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) {
65796579
if (isContextSensitive(func)) {
65806580
let contextualSignature = getContextualSignature(func);
65816581
if (contextualSignature) {
@@ -6907,7 +6907,7 @@ namespace ts {
69076907
}
69086908
}
69096909

6910-
function isFunctionExpressionOrArrowFunction(node: Node): boolean {
6910+
function isFunctionExpressionOrArrowFunction(node: Node): node is FunctionExpression {
69116911
return node.kind === SyntaxKind.FunctionExpression || node.kind === SyntaxKind.ArrowFunction;
69126912
}
69136913

@@ -6926,8 +6926,8 @@ namespace ts {
69266926
function getContextualSignature(node: FunctionExpression | MethodDeclaration): Signature {
69276927
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
69286928
let type = isObjectLiteralMethod(node)
6929-
? getContextualTypeForObjectLiteralMethod(<MethodDeclaration>node)
6930-
: getContextualType(<FunctionExpression>node);
6929+
? getContextualTypeForObjectLiteralMethod(node)
6930+
: getContextualType(node);
69316931
if (!type) {
69326932
return undefined;
69336933
}
@@ -13656,7 +13656,7 @@ namespace ts {
1365613656
forEach(node.decorators, checkFunctionAndClassExpressionBodies);
1365713657
forEach((<MethodDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
1365813658
if (isObjectLiteralMethod(node)) {
13659-
checkFunctionExpressionOrObjectLiteralMethodBody(<MethodDeclaration>node);
13659+
checkFunctionExpressionOrObjectLiteralMethodBody(node);
1366013660
}
1366113661
break;
1366213662
case SyntaxKind.Constructor:

src/compiler/utilities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ namespace ts {
660660
return node && node.kind === SyntaxKind.Block && isFunctionLike(node.parent);
661661
}
662662

663-
export function isObjectLiteralMethod(node: Node) {
663+
export function isObjectLiteralMethod(node: Node): node is MethodDeclaration {
664664
return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression;
665665
}
666666

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts(17,24): error TS7006: Parameter 'arg' implicitly has an 'any' type.
2+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts(20,24): error TS7006: Parameter 'arg' implicitly has an 'any' type.
3+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts(28,27): error TS7006: Parameter 'arg' implicitly has an 'any' type.
4+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts(31,27): error TS7006: Parameter 'arg' implicitly has an 'any' type.
5+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts(39,36): error TS7006: Parameter 'arg' implicitly has an 'any' type.
6+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts(42,36): error TS7006: Parameter 'arg' implicitly has an 'any' type.
7+
8+
9+
==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration01.ts (6 errors) ====
10+
11+
interface A {
12+
numProp: number;
13+
}
14+
15+
interface B {
16+
strProp: string;
17+
}
18+
19+
interface Foo {
20+
method1(arg: A): void;
21+
method2(arg: B): void;
22+
}
23+
24+
function getFoo1(): Foo {
25+
return class {
26+
static method1(arg) {
27+
~~~
28+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
29+
arg.numProp = 10;
30+
}
31+
static method2(arg) {
32+
~~~
33+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
34+
arg.strProp = "hello";
35+
}
36+
}
37+
}
38+
39+
function getFoo2(): Foo {
40+
return class {
41+
static method1 = (arg) => {
42+
~~~
43+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
44+
arg.numProp = 10;
45+
}
46+
static method2 = (arg) => {
47+
~~~
48+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
49+
arg.strProp = "hello";
50+
}
51+
}
52+
}
53+
54+
function getFoo3(): Foo {
55+
return class {
56+
static method1 = function (arg) {
57+
~~~
58+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
59+
arg.numProp = 10;
60+
}
61+
static method2 = function (arg) {
62+
~~~
63+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
64+
arg.strProp = "hello";
65+
}
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//// [contextuallyTypedClassExpressionMethodDeclaration01.ts]
2+
3+
interface A {
4+
numProp: number;
5+
}
6+
7+
interface B {
8+
strProp: string;
9+
}
10+
11+
interface Foo {
12+
method1(arg: A): void;
13+
method2(arg: B): void;
14+
}
15+
16+
function getFoo1(): Foo {
17+
return class {
18+
static method1(arg) {
19+
arg.numProp = 10;
20+
}
21+
static method2(arg) {
22+
arg.strProp = "hello";
23+
}
24+
}
25+
}
26+
27+
function getFoo2(): Foo {
28+
return class {
29+
static method1 = (arg) => {
30+
arg.numProp = 10;
31+
}
32+
static method2 = (arg) => {
33+
arg.strProp = "hello";
34+
}
35+
}
36+
}
37+
38+
function getFoo3(): Foo {
39+
return class {
40+
static method1 = function (arg) {
41+
arg.numProp = 10;
42+
}
43+
static method2 = function (arg) {
44+
arg.strProp = "hello";
45+
}
46+
}
47+
}
48+
49+
//// [contextuallyTypedClassExpressionMethodDeclaration01.js]
50+
function getFoo1() {
51+
return (function () {
52+
function class_1() {
53+
}
54+
class_1.method1 = function (arg) {
55+
arg.numProp = 10;
56+
};
57+
class_1.method2 = function (arg) {
58+
arg.strProp = "hello";
59+
};
60+
return class_1;
61+
})();
62+
}
63+
function getFoo2() {
64+
return (function () {
65+
function class_2() {
66+
}
67+
class_2.method1 = function (arg) {
68+
arg.numProp = 10;
69+
};
70+
class_2.method2 = function (arg) {
71+
arg.strProp = "hello";
72+
};
73+
return class_2;
74+
})();
75+
}
76+
function getFoo3() {
77+
return (function () {
78+
function class_3() {
79+
}
80+
class_3.method1 = function (arg) {
81+
arg.numProp = 10;
82+
};
83+
class_3.method2 = function (arg) {
84+
arg.strProp = "hello";
85+
};
86+
return class_3;
87+
})();
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts(21,17): error TS7006: Parameter 'arg' implicitly has an 'any' type.
2+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts(24,17): error TS7006: Parameter 'arg' implicitly has an 'any' type.
3+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts(32,20): error TS7006: Parameter 'arg' implicitly has an 'any' type.
4+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts(35,20): error TS7006: Parameter 'arg' implicitly has an 'any' type.
5+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts(43,29): error TS7006: Parameter 'arg' implicitly has an 'any' type.
6+
tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts(46,29): error TS7006: Parameter 'arg' implicitly has an 'any' type.
7+
8+
9+
==== tests/cases/conformance/types/contextualTypes/methodDeclarations/contextuallyTypedClassExpressionMethodDeclaration02.ts (6 errors) ====
10+
11+
interface A {
12+
numProp: number;
13+
}
14+
15+
interface B {
16+
strProp: string;
17+
}
18+
19+
interface Foo {
20+
new (): Bar;
21+
}
22+
23+
interface Bar {
24+
method1(arg: A): void;
25+
method2(arg: B): void;
26+
}
27+
28+
function getFoo1(): Foo {
29+
return class {
30+
method1(arg) {
31+
~~~
32+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
33+
arg.numProp = 10;
34+
}
35+
method2(arg) {
36+
~~~
37+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
38+
arg.strProp = "hello";
39+
}
40+
}
41+
}
42+
43+
function getFoo2(): Foo {
44+
return class {
45+
method1 = (arg) => {
46+
~~~
47+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
48+
arg.numProp = 10;
49+
}
50+
method2 = (arg) => {
51+
~~~
52+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
53+
arg.strProp = "hello";
54+
}
55+
}
56+
}
57+
58+
function getFoo3(): Foo {
59+
return class {
60+
method1 = function (arg) {
61+
~~~
62+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
63+
arg.numProp = 10;
64+
}
65+
method2 = function (arg) {
66+
~~~
67+
!!! error TS7006: Parameter 'arg' implicitly has an 'any' type.
68+
arg.strProp = "hello";
69+
}
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
//// [contextuallyTypedClassExpressionMethodDeclaration02.ts]
2+
3+
interface A {
4+
numProp: number;
5+
}
6+
7+
interface B {
8+
strProp: string;
9+
}
10+
11+
interface Foo {
12+
new (): Bar;
13+
}
14+
15+
interface Bar {
16+
method1(arg: A): void;
17+
method2(arg: B): void;
18+
}
19+
20+
function getFoo1(): Foo {
21+
return class {
22+
method1(arg) {
23+
arg.numProp = 10;
24+
}
25+
method2(arg) {
26+
arg.strProp = "hello";
27+
}
28+
}
29+
}
30+
31+
function getFoo2(): Foo {
32+
return class {
33+
method1 = (arg) => {
34+
arg.numProp = 10;
35+
}
36+
method2 = (arg) => {
37+
arg.strProp = "hello";
38+
}
39+
}
40+
}
41+
42+
function getFoo3(): Foo {
43+
return class {
44+
method1 = function (arg) {
45+
arg.numProp = 10;
46+
}
47+
method2 = function (arg) {
48+
arg.strProp = "hello";
49+
}
50+
}
51+
}
52+
53+
//// [contextuallyTypedClassExpressionMethodDeclaration02.js]
54+
function getFoo1() {
55+
return (function () {
56+
function class_1() {
57+
}
58+
class_1.prototype.method1 = function (arg) {
59+
arg.numProp = 10;
60+
};
61+
class_1.prototype.method2 = function (arg) {
62+
arg.strProp = "hello";
63+
};
64+
return class_1;
65+
})();
66+
}
67+
function getFoo2() {
68+
return (function () {
69+
function class_2() {
70+
this.method1 = function (arg) {
71+
arg.numProp = 10;
72+
};
73+
this.method2 = function (arg) {
74+
arg.strProp = "hello";
75+
};
76+
}
77+
return class_2;
78+
})();
79+
}
80+
function getFoo3() {
81+
return (function () {
82+
function class_3() {
83+
this.method1 = function (arg) {
84+
arg.numProp = 10;
85+
};
86+
this.method2 = function (arg) {
87+
arg.strProp = "hello";
88+
};
89+
}
90+
return class_3;
91+
})();
92+
}

0 commit comments

Comments
 (0)