mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-14 19:16:17 -06:00
Allow local class declarations to be returned as mixins (#22807)
This commit is contained in:
parent
874dd25494
commit
a7b066fe04
@ -3185,7 +3185,9 @@ namespace ts {
|
||||
}
|
||||
else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral &&
|
||||
type.symbol.valueDeclaration &&
|
||||
type.symbol.valueDeclaration.kind === SyntaxKind.ClassExpression) {
|
||||
isClassLike(type.symbol.valueDeclaration) &&
|
||||
!isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)
|
||||
) {
|
||||
return createAnonymousTypeNode(type);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -0,0 +1,109 @@
|
||||
//// [declarationEmitLocalClassDeclarationMixin.ts]
|
||||
interface Constructor<C> { new (...args: any[]): C; }
|
||||
|
||||
function mixin<B extends Constructor<{}>>(Base: B) {
|
||||
class PrivateMixed extends Base {
|
||||
bar = 2;
|
||||
}
|
||||
return PrivateMixed;
|
||||
}
|
||||
|
||||
export class Unmixed {
|
||||
foo = 1;
|
||||
}
|
||||
|
||||
export const Mixed = mixin(Unmixed);
|
||||
|
||||
function Filter<C extends Constructor<{}>>(ctor: C) {
|
||||
abstract class FilterMixin extends ctor {
|
||||
abstract match(path: string): boolean;
|
||||
// other concrete methods, fields, constructor
|
||||
thing = 12;
|
||||
}
|
||||
return FilterMixin;
|
||||
}
|
||||
|
||||
export class FilteredThing extends Filter(Unmixed) {
|
||||
match(path: string) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [declarationEmitLocalClassDeclarationMixin.js]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var 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 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 mixin(Base) {
|
||||
var PrivateMixed = /** @class */ (function (_super) {
|
||||
__extends(PrivateMixed, _super);
|
||||
function PrivateMixed() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
_this.bar = 2;
|
||||
return _this;
|
||||
}
|
||||
return PrivateMixed;
|
||||
}(Base));
|
||||
return PrivateMixed;
|
||||
}
|
||||
var Unmixed = /** @class */ (function () {
|
||||
function Unmixed() {
|
||||
this.foo = 1;
|
||||
}
|
||||
return Unmixed;
|
||||
}());
|
||||
exports.Unmixed = Unmixed;
|
||||
exports.Mixed = mixin(Unmixed);
|
||||
function Filter(ctor) {
|
||||
var FilterMixin = /** @class */ (function (_super) {
|
||||
__extends(FilterMixin, _super);
|
||||
function FilterMixin() {
|
||||
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||
// other concrete methods, fields, constructor
|
||||
_this.thing = 12;
|
||||
return _this;
|
||||
}
|
||||
return FilterMixin;
|
||||
}(ctor));
|
||||
return FilterMixin;
|
||||
}
|
||||
var FilteredThing = /** @class */ (function (_super) {
|
||||
__extends(FilteredThing, _super);
|
||||
function FilteredThing() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
FilteredThing.prototype.match = function (path) {
|
||||
return false;
|
||||
};
|
||||
return FilteredThing;
|
||||
}(Filter(Unmixed)));
|
||||
exports.FilteredThing = FilteredThing;
|
||||
|
||||
|
||||
//// [declarationEmitLocalClassDeclarationMixin.d.ts]
|
||||
export declare class Unmixed {
|
||||
foo: number;
|
||||
}
|
||||
export declare const Mixed: {
|
||||
new (...args: any[]): {
|
||||
bar: number;
|
||||
};
|
||||
} & typeof Unmixed;
|
||||
declare const FilteredThing_base: {
|
||||
new (...args: any[]): {
|
||||
match(path: string): boolean;
|
||||
thing: number;
|
||||
};
|
||||
} & typeof Unmixed;
|
||||
export declare class FilteredThing extends FilteredThing_base {
|
||||
match(path: string): boolean;
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
=== tests/cases/compiler/declarationEmitLocalClassDeclarationMixin.ts ===
|
||||
interface Constructor<C> { new (...args: any[]): C; }
|
||||
>Constructor : Symbol(Constructor, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 0))
|
||||
>C : Symbol(C, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 22))
|
||||
>args : Symbol(args, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 32))
|
||||
>C : Symbol(C, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 22))
|
||||
|
||||
function mixin<B extends Constructor<{}>>(Base: B) {
|
||||
>mixin : Symbol(mixin, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 53))
|
||||
>B : Symbol(B, Decl(declarationEmitLocalClassDeclarationMixin.ts, 2, 15))
|
||||
>Constructor : Symbol(Constructor, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 0))
|
||||
>Base : Symbol(Base, Decl(declarationEmitLocalClassDeclarationMixin.ts, 2, 42))
|
||||
>B : Symbol(B, Decl(declarationEmitLocalClassDeclarationMixin.ts, 2, 15))
|
||||
|
||||
class PrivateMixed extends Base {
|
||||
>PrivateMixed : Symbol(PrivateMixed, Decl(declarationEmitLocalClassDeclarationMixin.ts, 2, 52))
|
||||
>Base : Symbol(Base, Decl(declarationEmitLocalClassDeclarationMixin.ts, 2, 42))
|
||||
|
||||
bar = 2;
|
||||
>bar : Symbol(PrivateMixed.bar, Decl(declarationEmitLocalClassDeclarationMixin.ts, 3, 37))
|
||||
}
|
||||
return PrivateMixed;
|
||||
>PrivateMixed : Symbol(PrivateMixed, Decl(declarationEmitLocalClassDeclarationMixin.ts, 2, 52))
|
||||
}
|
||||
|
||||
export class Unmixed {
|
||||
>Unmixed : Symbol(Unmixed, Decl(declarationEmitLocalClassDeclarationMixin.ts, 7, 1))
|
||||
|
||||
foo = 1;
|
||||
>foo : Symbol(Unmixed.foo, Decl(declarationEmitLocalClassDeclarationMixin.ts, 9, 22))
|
||||
}
|
||||
|
||||
export const Mixed = mixin(Unmixed);
|
||||
>Mixed : Symbol(Mixed, Decl(declarationEmitLocalClassDeclarationMixin.ts, 13, 12))
|
||||
>mixin : Symbol(mixin, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 53))
|
||||
>Unmixed : Symbol(Unmixed, Decl(declarationEmitLocalClassDeclarationMixin.ts, 7, 1))
|
||||
|
||||
function Filter<C extends Constructor<{}>>(ctor: C) {
|
||||
>Filter : Symbol(Filter, Decl(declarationEmitLocalClassDeclarationMixin.ts, 13, 36))
|
||||
>C : Symbol(C, Decl(declarationEmitLocalClassDeclarationMixin.ts, 15, 16))
|
||||
>Constructor : Symbol(Constructor, Decl(declarationEmitLocalClassDeclarationMixin.ts, 0, 0))
|
||||
>ctor : Symbol(ctor, Decl(declarationEmitLocalClassDeclarationMixin.ts, 15, 43))
|
||||
>C : Symbol(C, Decl(declarationEmitLocalClassDeclarationMixin.ts, 15, 16))
|
||||
|
||||
abstract class FilterMixin extends ctor {
|
||||
>FilterMixin : Symbol(FilterMixin, Decl(declarationEmitLocalClassDeclarationMixin.ts, 15, 53))
|
||||
>ctor : Symbol(ctor, Decl(declarationEmitLocalClassDeclarationMixin.ts, 15, 43))
|
||||
|
||||
abstract match(path: string): boolean;
|
||||
>match : Symbol(FilterMixin.match, Decl(declarationEmitLocalClassDeclarationMixin.ts, 16, 45))
|
||||
>path : Symbol(path, Decl(declarationEmitLocalClassDeclarationMixin.ts, 17, 23))
|
||||
|
||||
// other concrete methods, fields, constructor
|
||||
thing = 12;
|
||||
>thing : Symbol(FilterMixin.thing, Decl(declarationEmitLocalClassDeclarationMixin.ts, 17, 46))
|
||||
}
|
||||
return FilterMixin;
|
||||
>FilterMixin : Symbol(FilterMixin, Decl(declarationEmitLocalClassDeclarationMixin.ts, 15, 53))
|
||||
}
|
||||
|
||||
export class FilteredThing extends Filter(Unmixed) {
|
||||
>FilteredThing : Symbol(FilteredThing, Decl(declarationEmitLocalClassDeclarationMixin.ts, 22, 1))
|
||||
>Filter : Symbol(Filter, Decl(declarationEmitLocalClassDeclarationMixin.ts, 13, 36))
|
||||
>Unmixed : Symbol(Unmixed, Decl(declarationEmitLocalClassDeclarationMixin.ts, 7, 1))
|
||||
|
||||
match(path: string) {
|
||||
>match : Symbol(FilteredThing.match, Decl(declarationEmitLocalClassDeclarationMixin.ts, 24, 52))
|
||||
>path : Symbol(path, Decl(declarationEmitLocalClassDeclarationMixin.ts, 25, 10))
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
=== tests/cases/compiler/declarationEmitLocalClassDeclarationMixin.ts ===
|
||||
interface Constructor<C> { new (...args: any[]): C; }
|
||||
>Constructor : Constructor<C>
|
||||
>C : C
|
||||
>args : any[]
|
||||
>C : C
|
||||
|
||||
function mixin<B extends Constructor<{}>>(Base: B) {
|
||||
>mixin : <B extends Constructor<{}>>(Base: B) => { new (...args: any[]): PrivateMixed; prototype: mixin<any>.PrivateMixed; } & B
|
||||
>B : B
|
||||
>Constructor : Constructor<C>
|
||||
>Base : B
|
||||
>B : B
|
||||
|
||||
class PrivateMixed extends Base {
|
||||
>PrivateMixed : PrivateMixed
|
||||
>Base : {}
|
||||
|
||||
bar = 2;
|
||||
>bar : number
|
||||
>2 : 2
|
||||
}
|
||||
return PrivateMixed;
|
||||
>PrivateMixed : { new (...args: any[]): PrivateMixed; prototype: mixin<any>.PrivateMixed; } & B
|
||||
}
|
||||
|
||||
export class Unmixed {
|
||||
>Unmixed : Unmixed
|
||||
|
||||
foo = 1;
|
||||
>foo : number
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
export const Mixed = mixin(Unmixed);
|
||||
>Mixed : { new (...args: any[]): mixin<typeof Unmixed>.PrivateMixed; prototype: mixin<any>.PrivateMixed; } & typeof Unmixed
|
||||
>mixin(Unmixed) : { new (...args: any[]): mixin<typeof Unmixed>.PrivateMixed; prototype: mixin<any>.PrivateMixed; } & typeof Unmixed
|
||||
>mixin : <B extends Constructor<{}>>(Base: B) => { new (...args: any[]): PrivateMixed; prototype: mixin<any>.PrivateMixed; } & B
|
||||
>Unmixed : typeof Unmixed
|
||||
|
||||
function Filter<C extends Constructor<{}>>(ctor: C) {
|
||||
>Filter : <C extends Constructor<{}>>(ctor: C) => { new (...args: any[]): FilterMixin; prototype: Filter<any>.FilterMixin; } & C
|
||||
>C : C
|
||||
>Constructor : Constructor<C>
|
||||
>ctor : C
|
||||
>C : C
|
||||
|
||||
abstract class FilterMixin extends ctor {
|
||||
>FilterMixin : FilterMixin
|
||||
>ctor : {}
|
||||
|
||||
abstract match(path: string): boolean;
|
||||
>match : (path: string) => boolean
|
||||
>path : string
|
||||
|
||||
// other concrete methods, fields, constructor
|
||||
thing = 12;
|
||||
>thing : number
|
||||
>12 : 12
|
||||
}
|
||||
return FilterMixin;
|
||||
>FilterMixin : { new (...args: any[]): FilterMixin; prototype: Filter<any>.FilterMixin; } & C
|
||||
}
|
||||
|
||||
export class FilteredThing extends Filter(Unmixed) {
|
||||
>FilteredThing : FilteredThing
|
||||
>Filter(Unmixed) : Filter<typeof Unmixed>.FilterMixin & Unmixed
|
||||
>Filter : <C extends Constructor<{}>>(ctor: C) => { new (...args: any[]): FilterMixin; prototype: Filter<any>.FilterMixin; } & C
|
||||
>Unmixed : typeof Unmixed
|
||||
|
||||
match(path: string) {
|
||||
>match : (path: string) => boolean
|
||||
>path : string
|
||||
|
||||
return false;
|
||||
>false : false
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
// @declaration: true
|
||||
interface Constructor<C> { new (...args: any[]): C; }
|
||||
|
||||
function mixin<B extends Constructor<{}>>(Base: B) {
|
||||
class PrivateMixed extends Base {
|
||||
bar = 2;
|
||||
}
|
||||
return PrivateMixed;
|
||||
}
|
||||
|
||||
export class Unmixed {
|
||||
foo = 1;
|
||||
}
|
||||
|
||||
export const Mixed = mixin(Unmixed);
|
||||
|
||||
function Filter<C extends Constructor<{}>>(ctor: C) {
|
||||
abstract class FilterMixin extends ctor {
|
||||
abstract match(path: string): boolean;
|
||||
// other concrete methods, fields, constructor
|
||||
thing = 12;
|
||||
}
|
||||
return FilterMixin;
|
||||
}
|
||||
|
||||
export class FilteredThing extends Filter(Unmixed) {
|
||||
match(path: string) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user