mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix decorator design:types emit for type variables.
Previously, TypeScript would resolve the reified types for the
`design:types` decorator emit in the regular `currentScope`. That scope
does not include class declaration bodies.
However when reifying types, class declarations do introduce a new scope
for any `TypeVariable`s declared on them. Because TS resolved the
EntityName for such types against the parent scope (e.g. the source
file), not the class scope, TypeScript would either fail to resolve the type (giving `TypeReferenceSerializationKind.Unknown`), or
incorrectly resolve to a different, accidentally matching symbol in the outer scope (giving `TypeWithConstructSignatureAndValue`).
This would result in an emit referencing an undeclared symbol, or
mis-referencing the wrong symbol.
__metadata("design:type", typeof (_a = typeof TypeVariable !== "undefined" && TypeVariable) === "function" && _a || Object)
__metadata("design:type", TypeVariable)
This change special cases `currentScope` for
`serializeTypeReferenceNode` to use a class scope, if present. This
changes the emit for a `TypeVariable` back to `Object`:
__metadata("design:type", Object)
This commit is contained in:
@@ -1969,7 +1969,16 @@ namespace ts {
|
||||
* @param node The type reference node.
|
||||
*/
|
||||
function serializeTypeReferenceNode(node: TypeReferenceNode): SerializedTypeNode {
|
||||
const kind = resolver.getTypeReferenceSerializationKind(node.typeName, currentScope);
|
||||
// node might be a reference to type variable, which can be scoped to a class declaration, in addition to the regular
|
||||
// TypeScript scopes. Walk up the AST to find the next class and use that as the lookup scope.
|
||||
let scope: Node = node;
|
||||
while (scope.parent && scope !== currentScope) {
|
||||
scope = scope.parent;
|
||||
if (isClassDeclaration(scope)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const kind = resolver.getTypeReferenceSerializationKind(node.typeName, scope);
|
||||
switch (kind) {
|
||||
case TypeReferenceSerializationKind.Unknown:
|
||||
const serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts(2,4): error TS2304: Cannot find name 'Decorate'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts (1 errors) ====
|
||||
export class C<TypeVariable> {
|
||||
@Decorate
|
||||
~~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'Decorate'.
|
||||
member: TypeVariable;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
//// [decoratorMetadataGenericTypeVariable.ts]
|
||||
export class C<TypeVariable> {
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
}
|
||||
|
||||
|
||||
//// [decoratorMetadataGenericTypeVariable.js]
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
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;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
exports.__esModule = true;
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
__decorate([
|
||||
Decorate,
|
||||
__metadata("design:type", Object)
|
||||
], C.prototype, "member");
|
||||
return C;
|
||||
}());
|
||||
exports.C = C;
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts ===
|
||||
export class C<TypeVariable> {
|
||||
>C : Symbol(C, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 0))
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 15))
|
||||
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
>member : Symbol(C.member, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 30))
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 15))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
=== tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts ===
|
||||
export class C<TypeVariable> {
|
||||
>C : C<TypeVariable>
|
||||
>TypeVariable : TypeVariable
|
||||
|
||||
@Decorate
|
||||
>Decorate : any
|
||||
|
||||
member: TypeVariable;
|
||||
>member : TypeVariable
|
||||
>TypeVariable : TypeVariable
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts(2,4): error TS2304: Cannot find name 'Decorate'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts (1 errors) ====
|
||||
export class C<TypeVariable = string> {
|
||||
@Decorate
|
||||
~~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'Decorate'.
|
||||
member: TypeVariable;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
//// [decoratorMetadataGenericTypeVariableDefault.ts]
|
||||
export class C<TypeVariable = string> {
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
}
|
||||
|
||||
|
||||
//// [decoratorMetadataGenericTypeVariableDefault.js]
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
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;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
exports.__esModule = true;
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
__decorate([
|
||||
Decorate,
|
||||
__metadata("design:type", Object)
|
||||
], C.prototype, "member");
|
||||
return C;
|
||||
}());
|
||||
exports.C = C;
|
||||
@@ -0,0 +1,11 @@
|
||||
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts ===
|
||||
export class C<TypeVariable = string> {
|
||||
>C : Symbol(C, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 0))
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 15))
|
||||
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
>member : Symbol(C.member, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 39))
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 15))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts ===
|
||||
export class C<TypeVariable = string> {
|
||||
>C : C<TypeVariable>
|
||||
>TypeVariable : TypeVariable
|
||||
|
||||
@Decorate
|
||||
>Decorate : any
|
||||
|
||||
member: TypeVariable;
|
||||
>member : TypeVariable
|
||||
>TypeVariable : TypeVariable
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts(5,4): error TS2304: Cannot find name 'Decorate'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts (1 errors) ====
|
||||
// Unused, but could collide with the named type argument below.
|
||||
class TypeVariable {}
|
||||
|
||||
export class C<TypeVariable> {
|
||||
@Decorate
|
||||
~~~~~~~~
|
||||
!!! error TS2304: Cannot find name 'Decorate'.
|
||||
member: TypeVariable;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//// [decoratorMetadataGenericTypeVariableInScope.ts]
|
||||
// Unused, but could collide with the named type argument below.
|
||||
class TypeVariable {}
|
||||
|
||||
export class C<TypeVariable> {
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
}
|
||||
|
||||
|
||||
//// [decoratorMetadataGenericTypeVariableInScope.js]
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
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;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
exports.__esModule = true;
|
||||
// Unused, but could collide with the named type argument below.
|
||||
var TypeVariable = /** @class */ (function () {
|
||||
function TypeVariable() {
|
||||
}
|
||||
return TypeVariable;
|
||||
}());
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
__decorate([
|
||||
Decorate,
|
||||
__metadata("design:type", Object)
|
||||
], C.prototype, "member");
|
||||
return C;
|
||||
}());
|
||||
exports.C = C;
|
||||
@@ -0,0 +1,15 @@
|
||||
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts ===
|
||||
// Unused, but could collide with the named type argument below.
|
||||
class TypeVariable {}
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 0, 0))
|
||||
|
||||
export class C<TypeVariable> {
|
||||
>C : Symbol(C, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 1, 21))
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 3, 15))
|
||||
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
>member : Symbol(C.member, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 3, 30))
|
||||
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 3, 15))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts ===
|
||||
// Unused, but could collide with the named type argument below.
|
||||
class TypeVariable {}
|
||||
>TypeVariable : TypeVariable
|
||||
|
||||
export class C<TypeVariable> {
|
||||
>C : C<TypeVariable>
|
||||
>TypeVariable : TypeVariable
|
||||
|
||||
@Decorate
|
||||
>Decorate : any
|
||||
|
||||
member: TypeVariable;
|
||||
>member : TypeVariable
|
||||
>TypeVariable : TypeVariable
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// @experimentalDecorators: true
|
||||
// @emitDecoratorMetadata: true
|
||||
|
||||
export class C<TypeVariable> {
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// @experimentalDecorators: true
|
||||
// @emitDecoratorMetadata: true
|
||||
|
||||
export class C<TypeVariable = string> {
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// @experimentalDecorators: true
|
||||
// @emitDecoratorMetadata: true
|
||||
|
||||
// Unused, but could collide with the named type argument below.
|
||||
class TypeVariable {}
|
||||
|
||||
export class C<TypeVariable> {
|
||||
@Decorate
|
||||
member: TypeVariable;
|
||||
}
|
||||
Reference in New Issue
Block a user