Skip to content

Commit cfb0ade

Browse files
authored
Merge pull request #28609 from ajafff/class-decorator-generics
resolve TypeReference in class decorator at parent of class
2 parents a0f122b + 12ef619 commit cfb0ade

File tree

5 files changed

+109
-1
lines changed

5 files changed

+109
-1
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,14 @@ namespace ts {
14741474
// @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
14751475
// }
14761476
//
1477-
if (location.parent && isClassElement(location.parent)) {
1477+
1478+
// class Decorators are resolved outside of the class to avoid referencing type parameters of that class.
1479+
//
1480+
// type T = number;
1481+
// declare function y(x: T): any;
1482+
// @param(1 as T) // <-- T should resolve to the type alias outside of class C
1483+
// class C<T> {}
1484+
if (location.parent && (isClassElement(location.parent) || location.parent.kind === SyntaxKind.ClassDeclaration)) {
14781485
location = location.parent;
14791486
}
14801487
break;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//// [decoratorReferences.ts]
2+
declare function y(...args: any[]): any;
3+
type T = number;
4+
@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
5+
class C<T> {
6+
@y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class
7+
method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
8+
}
9+
10+
//// [decoratorReferences.js]
11+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
12+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
13+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
14+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
15+
return c > 3 && r && Object.defineProperty(target, key, r), r;
16+
};
17+
var __param = (this && this.__param) || function (paramIndex, decorator) {
18+
return function (target, key) { decorator(target, key, paramIndex); }
19+
};
20+
var C = /** @class */ (function () {
21+
function C() {
22+
}
23+
C_1 = C;
24+
C.prototype.method = function (x, y) { }; // <-- decorator y should be resolved at the class declaration, not the parameter.
25+
var C_1;
26+
__decorate([
27+
y(null) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class
28+
,
29+
__param(0, y)
30+
], C.prototype, "method");
31+
C = C_1 = __decorate([
32+
y(1, C_1) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
33+
], C);
34+
return C;
35+
}());
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/decoratorReferences.ts ===
2+
declare function y(...args: any[]): any;
3+
>y : Symbol(y, Decl(decoratorReferences.ts, 0, 0))
4+
>args : Symbol(args, Decl(decoratorReferences.ts, 0, 19))
5+
6+
type T = number;
7+
>T : Symbol(T, Decl(decoratorReferences.ts, 0, 40))
8+
9+
@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
10+
>y : Symbol(y, Decl(decoratorReferences.ts, 0, 0))
11+
>T : Symbol(T, Decl(decoratorReferences.ts, 0, 40))
12+
>C : Symbol(C, Decl(decoratorReferences.ts, 1, 16))
13+
14+
class C<T> {
15+
>C : Symbol(C, Decl(decoratorReferences.ts, 1, 16))
16+
>T : Symbol(T, Decl(decoratorReferences.ts, 3, 8))
17+
18+
@y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class
19+
>y : Symbol(y, Decl(decoratorReferences.ts, 0, 0))
20+
>T : Symbol(T, Decl(decoratorReferences.ts, 3, 8))
21+
22+
method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
23+
>method : Symbol(C.method, Decl(decoratorReferences.ts, 3, 12))
24+
>y : Symbol(y, Decl(decoratorReferences.ts, 0, 0))
25+
>x : Symbol(x, Decl(decoratorReferences.ts, 5, 11))
26+
>y : Symbol(y, Decl(decoratorReferences.ts, 5, 16))
27+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/compiler/decoratorReferences.ts ===
2+
declare function y(...args: any[]): any;
3+
>y : (...args: any[]) => any
4+
>args : any[]
5+
6+
type T = number;
7+
>T : number
8+
9+
@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
10+
>y(1 as T, C) : any
11+
>y : (...args: any[]) => any
12+
>1 as T : number
13+
>1 : 1
14+
>C : typeof C
15+
16+
class C<T> {
17+
>C : C<T>
18+
19+
@y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class
20+
>y(null as T) : any
21+
>y : (...args: any[]) => any
22+
>null as T : T
23+
>null : null
24+
25+
method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
26+
>method : (x: any, y: any) => void
27+
>y : (...args: any[]) => any
28+
>x : any
29+
>y : any
30+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @experimentalDecorators: true
2+
3+
declare function y(...args: any[]): any;
4+
type T = number;
5+
@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
6+
class C<T> {
7+
@y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class
8+
method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
9+
}

0 commit comments

Comments
 (0)