diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ed3057895fae8..85ee12637eef6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4087,8 +4087,6 @@ namespace ts { else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && isClassLike(type.symbol.valueDeclaration) && - // Use `import` types for refs to other scopes, only anonymize something defined in the same scope - findAncestor(type.symbol.valueDeclaration, d => d === getSourceFileOfNode(context.enclosingDeclaration)) && !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration) ) { return createAnonymousTypeNode(type); diff --git a/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js new file mode 100644 index 0000000000000..697348e1ba834 --- /dev/null +++ b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.js @@ -0,0 +1,142 @@ +//// [tests/cases/compiler/anonClassDeclarationEmitIsAnon.ts] //// + +//// [wrapClass.ts] +export function wrapClass(param: any) { + return class Wrapped { + foo() { + return param; + } + } +} + +export type Constructor = new (...args: any[]) => T; + +export function Timestamped(Base: TBase) { + return class extends Base { + timestamp = Date.now(); + }; +} + +//// [index.ts] +import { wrapClass, Timestamped } from "./wrapClass"; + +export default wrapClass(0); + +// Simple class +export class User { + name = ''; +} + +// User that is Timestamped +export class TimestampedUser extends Timestamped(User) { + constructor() { + super(); + } +} + +//// [wrapClass.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +function wrapClass(param) { + return /** @class */ (function () { + function Wrapped() { + } + Wrapped.prototype.foo = function () { + return param; + }; + return Wrapped; + }()); +} +exports.wrapClass = wrapClass; +function Timestamped(Base) { + return /** @class */ (function (_super) { + __extends(class_1, _super); + function class_1() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.timestamp = Date.now(); + return _this; + } + return class_1; + }(Base)); +} +exports.Timestamped = Timestamped; +//// [index.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var wrapClass_1 = require("./wrapClass"); +exports["default"] = wrapClass_1.wrapClass(0); +// Simple class +var User = /** @class */ (function () { + function User() { + this.name = ''; + } + return User; +}()); +exports.User = User; +// User that is Timestamped +var TimestampedUser = /** @class */ (function (_super) { + __extends(TimestampedUser, _super); + function TimestampedUser() { + return _super.call(this) || this; + } + return TimestampedUser; +}(wrapClass_1.Timestamped(User))); +exports.TimestampedUser = TimestampedUser; + + +//// [wrapClass.d.ts] +export declare function wrapClass(param: any): { + new (): { + foo(): any; + }; +}; +export declare type Constructor = new (...args: any[]) => T; +export declare function Timestamped(Base: TBase): { + new (...args: any[]): { + timestamp: number; + }; +} & TBase; +//// [index.d.ts] +declare const _default: { + new (): { + foo(): any; + }; +}; +export default _default; +export declare class User { + name: string; +} +declare const TimestampedUser_base: { + new (...args: any[]): { + timestamp: number; + }; +} & typeof User; +export declare class TimestampedUser extends TimestampedUser_base { + constructor(); +} diff --git a/tests/baselines/reference/anonClassDeclarationEmitIsAnon.symbols b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.symbols new file mode 100644 index 0000000000000..f2988d8cb2e6d --- /dev/null +++ b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.symbols @@ -0,0 +1,68 @@ +=== tests/cases/compiler/wrapClass.ts === +export function wrapClass(param: any) { +>wrapClass : Symbol(wrapClass, Decl(wrapClass.ts, 0, 0)) +>param : Symbol(param, Decl(wrapClass.ts, 0, 26)) + + return class Wrapped { +>Wrapped : Symbol(Wrapped, Decl(wrapClass.ts, 1, 10)) + + foo() { +>foo : Symbol(Wrapped.foo, Decl(wrapClass.ts, 1, 26)) + + return param; +>param : Symbol(param, Decl(wrapClass.ts, 0, 26)) + } + } +} + +export type Constructor = new (...args: any[]) => T; +>Constructor : Symbol(Constructor, Decl(wrapClass.ts, 6, 1)) +>T : Symbol(T, Decl(wrapClass.ts, 8, 24)) +>args : Symbol(args, Decl(wrapClass.ts, 8, 39)) +>T : Symbol(T, Decl(wrapClass.ts, 8, 24)) + +export function Timestamped(Base: TBase) { +>Timestamped : Symbol(Timestamped, Decl(wrapClass.ts, 8, 60)) +>TBase : Symbol(TBase, Decl(wrapClass.ts, 10, 28)) +>Constructor : Symbol(Constructor, Decl(wrapClass.ts, 6, 1)) +>Base : Symbol(Base, Decl(wrapClass.ts, 10, 55)) +>TBase : Symbol(TBase, Decl(wrapClass.ts, 10, 28)) + + return class extends Base { +>Base : Symbol(Base, Decl(wrapClass.ts, 10, 55)) + + timestamp = Date.now(); +>timestamp : Symbol((Anonymous class).timestamp, Decl(wrapClass.ts, 11, 31)) +>Date.now : Symbol(DateConstructor.now, Decl(lib.es5.d.ts, --, --)) +>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --)) +>now : Symbol(DateConstructor.now, Decl(lib.es5.d.ts, --, --)) + + }; +} + +=== tests/cases/compiler/index.ts === +import { wrapClass, Timestamped } from "./wrapClass"; +>wrapClass : Symbol(wrapClass, Decl(index.ts, 0, 8)) +>Timestamped : Symbol(Timestamped, Decl(index.ts, 0, 19)) + +export default wrapClass(0); +>wrapClass : Symbol(wrapClass, Decl(index.ts, 0, 8)) + +// Simple class +export class User { +>User : Symbol(User, Decl(index.ts, 2, 28)) + + name = ''; +>name : Symbol(User.name, Decl(index.ts, 5, 19)) +} + +// User that is Timestamped +export class TimestampedUser extends Timestamped(User) { +>TimestampedUser : Symbol(TimestampedUser, Decl(index.ts, 7, 1)) +>Timestamped : Symbol(Timestamped, Decl(index.ts, 0, 19)) +>User : Symbol(User, Decl(index.ts, 2, 28)) + + constructor() { + super(); + } +} diff --git a/tests/baselines/reference/anonClassDeclarationEmitIsAnon.types b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.types new file mode 100644 index 0000000000000..038b0a49bfbaa --- /dev/null +++ b/tests/baselines/reference/anonClassDeclarationEmitIsAnon.types @@ -0,0 +1,72 @@ +=== tests/cases/compiler/wrapClass.ts === +export function wrapClass(param: any) { +>wrapClass : (param: any) => typeof Wrapped +>param : any + + return class Wrapped { +>class Wrapped { foo() { return param; } } : typeof Wrapped +>Wrapped : typeof Wrapped + + foo() { +>foo : () => any + + return param; +>param : any + } + } +} + +export type Constructor = new (...args: any[]) => T; +>Constructor : Constructor +>args : any[] + +export function Timestamped(Base: TBase) { +>Timestamped : >(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Timestamped.(Anonymous class); } & TBase +>Base : TBase + + return class extends Base { +>class extends Base { timestamp = Date.now(); } : { new (...args: any[]): (Anonymous class); prototype: Timestamped.(Anonymous class); } & TBase +>Base : {} + + timestamp = Date.now(); +>timestamp : number +>Date.now() : number +>Date.now : () => number +>Date : DateConstructor +>now : () => number + + }; +} + +=== tests/cases/compiler/index.ts === +import { wrapClass, Timestamped } from "./wrapClass"; +>wrapClass : (param: any) => typeof Wrapped +>Timestamped : >(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Timestamped.(Anonymous class); } & TBase + +export default wrapClass(0); +>wrapClass(0) : typeof Wrapped +>wrapClass : (param: any) => typeof Wrapped +>0 : 0 + +// Simple class +export class User { +>User : User + + name = ''; +>name : string +>'' : "" +} + +// User that is Timestamped +export class TimestampedUser extends Timestamped(User) { +>TimestampedUser : TimestampedUser +>Timestamped(User) : Timestamped.(Anonymous class) & User +>Timestamped : >(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Timestamped.(Anonymous class); } & TBase +>User : typeof User + + constructor() { + super(); +>super() : void +>super : { new (...args: any[]): Timestamped.(Anonymous class); prototype: Timestamped.(Anonymous class); } & typeof User + } +} diff --git a/tests/cases/compiler/anonClassDeclarationEmitIsAnon.ts b/tests/cases/compiler/anonClassDeclarationEmitIsAnon.ts new file mode 100644 index 0000000000000..e7718e5c01b8d --- /dev/null +++ b/tests/cases/compiler/anonClassDeclarationEmitIsAnon.ts @@ -0,0 +1,34 @@ +// @declaration: true +// @filename: wrapClass.ts +export function wrapClass(param: any) { + return class Wrapped { + foo() { + return param; + } + } +} + +export type Constructor = new (...args: any[]) => T; + +export function Timestamped(Base: TBase) { + return class extends Base { + timestamp = Date.now(); + }; +} + +// @filename: index.ts +import { wrapClass, Timestamped } from "./wrapClass"; + +export default wrapClass(0); + +// Simple class +export class User { + name = ''; +} + +// User that is Timestamped +export class TimestampedUser extends Timestamped(User) { + constructor() { + super(); + } +} \ No newline at end of file