Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2838,7 +2838,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
else if (isClassLike(declaration)) {
// still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} })
return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration);
// or when used within a decorator in the class (e.g. `@dec(A.x) class A { static x = "x" }`),
// except when used in a function that is not an IIFE (e.g., `@dec(() => A.x) class A { ... }`)
const container = findAncestor(usage, n =>
n === declaration ? "quit" :
isComputedPropertyName(n) ? n.parent.parent === declaration :
isDecorator(n) && (n.parent === declaration ||
isMethodDeclaration(n.parent) && n.parent.parent === declaration ||
isGetOrSetAccessorDeclaration(n.parent) && n.parent.parent === declaration ||
isPropertyDeclaration(n.parent) && n.parent.parent === declaration ||
isParameter(n.parent) && n.parent.parent.parent === declaration));
if (!container) {
return true;
}
if (isDecorator(container)) {
return !!findAncestor(usage, n => n === container ? "quit" : isFunctionLike(n) && !getImmediatelyInvokedFunctionExpression(n));
}
return false;
}
else if (isPropertyDeclaration(declaration)) {
// still might be illegal if a self-referencing property initializer (eg private x = this.x)
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/decoratorReferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//// [decoratorReferences.ts]
declare function y(...args: any[]): any;
type T = number;
@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
@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
class C<T> {
@y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class
method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
Expand All @@ -29,7 +29,7 @@ var C = /** @class */ (function () {
__param(0, y)
], C.prototype, "method", null);
C = __decorate([
y(1, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
y(1, function () { return C; }) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class
], C);
return C;
}());
2 changes: 1 addition & 1 deletion tests/baselines/reference/decoratorReferences.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ declare function y(...args: any[]): any;
type T = number;
>T : Symbol(T, Decl(decoratorReferences.ts, 0, 40))

@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
@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
>y : Symbol(y, Decl(decoratorReferences.ts, 0, 0))
>T : Symbol(T, Decl(decoratorReferences.ts, 0, 40))
>C : Symbol(C, Decl(decoratorReferences.ts, 1, 16))
Expand Down
5 changes: 3 additions & 2 deletions tests/baselines/reference/decoratorReferences.types
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ declare function y(...args: any[]): any;
type T = number;
>T : number

@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
>y(1 as T, C) : any
@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
>y(1 as T, () => C) : any
>y : (...args: any[]) => any
>1 as T : number
>1 : 1
>() => C : () => typeof C
>C : typeof C

class C<T> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
useBeforeDeclaration_classDecorators.1.ts(7,6): error TS2449: Class 'C2' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(10,13): error TS2449: Class 'C3' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(29,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(30,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(31,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(32,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(33,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(35,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(36,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(37,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(38,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(39,10): error TS2449: Class 'C5' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(44,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(45,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(46,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(47,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(48,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(50,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(51,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(52,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(53,17): error TS2449: Class 'C6' used before its declaration.
useBeforeDeclaration_classDecorators.1.ts(54,17): error TS2449: Class 'C6' used before its declaration.


==== useBeforeDeclaration_classDecorators.1.ts (22 errors) ====
declare const dec: any;

// ok
@dec(() => C1) class C1 { }

// error
@dec(C2) class C2 { }
~~
!!! error TS2449: Class 'C2' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:7:16: 'C2' is declared here.

// error
@dec((() => C3)()) class C3 { }
~~
!!! error TS2449: Class 'C3' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:10:26: 'C3' is declared here.

// ok
class C4 {
@dec(() => C4) static method() {}
@dec(() => C4) static get x() { return this.y; }
@dec(() => C4) static set x(v) {}
@dec(() => C4) static y: any;
@dec(() => C4) static accessor z: any;

@dec(() => C4) method() {}
@dec(() => C4) get x() { return this.y; }
@dec(() => C4) set x(v) {}
@dec(() => C4) y: any;
@dec(() => C4) accessor z: any;
}

// error
class C5 {
@dec(C5) static method() {}
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) static get x() { return this.y; }
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) static set x(v) {}
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) static y: any;
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) static accessor z: any;
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.

@dec(C5) method() {}
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) get x() { return this.y; }
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) set x(v) {}
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) y: any;
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
@dec(C5) accessor z: any;
~~
!!! error TS2449: Class 'C5' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here.
}

// error
class C6 {
@dec((() => C6)()) static method() {}
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) static get x() { return this.y; }
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) static set x(v) {}
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) static y: any;
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) static accessor z: any;
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.

@dec((() => C6)()) method() {}
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) get x() { return this.y; }
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) set x(v) {}
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) y: any;
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
@dec((() => C6)()) accessor z: any;
~~
!!! error TS2449: Class 'C6' used before its declaration.
!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here.
}

Loading