可以在 TypeScript 中创建嵌套类吗?

有没有一种方法可以在 TypeScript 中嵌套类,例如:

var foo = new Foo();
var bar = new Foo.Bar();
106494 次浏览

在现代的 TypeScript 中,我们有可用于创建嵌套类的类表达式。例如,你可以这样做:

class Foo {
static Bar = class {
        

}
}


// works!
var foo = new Foo();
var bar = new Foo.Bar();

我无法在不收到编译错误的情况下让它与导出的类一起工作,所以我使用了 命名空间:

namespace MyNamespace {
export class Foo { }
}


namespace MyNamespace.Foo {
export class Bar { }
}

下面是一个使用 类表达式的更复杂的用例。

它允许 内部阶级访问 外层阶级。private成员

class classX {
private y: number = 0;


public getY(): number { return this.y; }


public utilities = new class {
constructor(public superThis: classX) {
}
public testSetOuterPrivate(target: number) {
this.superThis.y = target;
}
}(this);
}


const x1: classX = new classX();
alert(x1.getY());


x1.utilities.testSetOuterPrivate(4);
alert(x1.getY());

Codepen

如果处于类型声明文件的上下文中,可以通过混合类和命名空间来实现:

// foo.d.ts
declare class Foo {
constructor();
fooMethod(): any;
}


declare namespace Foo {
class Bar {
constructor();
barMethod(): any;
}
}


// ...elsewhere
const foo = new Foo();
const bar = new Foo.Bar();

这个答案是关于在@basarat 的答案之上构建的 TypeScript 中的 看似嵌套的类实现

要使 静电干扰嵌套类 Bar的类型可访问(如@PeterMoore 所指出的) ,请在命名空间中声明嵌套类的类型。这样,我们可以使用快捷方式 Foo.Bar。通过将类型 typeof Foo.Bar.prototype移动到声明的命名空间中的类型,我们不必重复表达式。

class Foo {
static Bar = class {
        

}
}


declare namespace Foo {
type Bar = typeof Foo.Bar.prototype
}


// Now we are able to use `Foo.Bar` as a type
let bar: Foo.Bar = new Foo.Bar()

对于静态类,下面的实现可能更优雅。

class Foo { }


namespace Foo {
export class Bar { }
}


let bar: Foo.Bar = new Foo.Bar()

要导出类,可以在类和命名空间声明之后添加导出语句,例如 export default Fooexport { Foo }

若要使用非静态嵌套类实现相同的目标,请参见下面的示例。

class Foo {
Bar = class {
        

}
}


declare namespace Foo.prototype {
type Bar = typeof Foo.prototype.Bar.prototype
}


let foo: Foo = new Foo()
let bar: Foo.prototype.Bar = new foo.Bar()

我希望这能有所帮助

能够:

  • 创建一个新的内部类实例
  • 访问外部类实例/原型成员
  • 实现接口
  • 用装潢师

用例

export interface Constructor<T> {
new(...args: any[]): T;
}


export interface Testable {
test(): void;
}


export function LogClassName<T>() {
return function (target: Constructor<T>) {
console.log(target.name);
}
}


class OuterClass {
private _prop1: string;


constructor(prop1: string) {
this._prop1 = prop1;
}


private method1(): string {
return 'private outer method 1';
}


public InnerClass = (
() => {
const $outer = this;


@LogClassName()
class InnerClass implements Testable {
private readonly _$outer: typeof $outer;


constructor(public innerProp1: string) {
this._$outer = $outer;
}


public test(): void {
console.log('test()');
}


public outerPrivateProp1(): string {
return this._$outer._prop1;
}
                

public outerPrivateMethod1(): string {
return this._$outer.method1();
}
}
return InnerClass;
}
)();
}


const outer = new OuterClass('outer prop 1')
const inner = new outer.InnerClass('inner prop 1');


console.log(inner instanceof outer.InnerClass); // true
console.log(inner.innerProp1); // inner prop 1
console.log(inner.outerPrivateProp1()); // outer prop 1
console.log(inner.outerPrivateMethod1()); // private outer method 1