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

wljmcqd8  于 2023-05-27  发布在  Java
关注(0)|答案(6)|浏览(170)

有没有一种方法可以在TypeScript中嵌套类。例如,我想使用它们:

var foo = new Foo();
var bar = new Foo.Bar();
3mpgtkmj

3mpgtkmj1#

在现代TypeScript中,我们有类表达式,可以用来创建嵌套类。例如,您可以执行以下操作:

class Foo {
    static Bar = class {
        
    }
}

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

slmsl1lt2#

下面是一个使用*类表达式*的更复杂的用例。
允许
内部类
访问外部类的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

neekobn8

neekobn83#

我无法在没有收到编译错误的情况下使用导出的类,而是使用namespaces

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}
j13ufse2

j13ufse24#

如果你在类型声明文件的上下文中,你可以通过混合类和命名空间来做到这一点:

// 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();
js81xvg6

js81xvg65#

  • 这个答案是关于嵌套类的无缝实现。*

定义Foo.Bar(静态)

定义静态嵌套类Foo.Bar可以通过以下两种方式完成。
1.选项1:在类Foo中定义嵌套类Bar。该类型在declare namespace声明中声明。
1.选项2:使用声明合并在Foo命名空间中使用export关键字定义嵌套类Bar

选项一:在类Foo中实现Bar

所有类都在一个块中实现,即在Foo类声明中。

class Foo {
    static Bar = class { }
}

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

let bar: Foo.Bar = new Foo.Bar()
选项二:在命名空间Foo中实现Bar

对于静态类,下面的实现可能对某些人来说更优雅。缺点是这个方法不能处理非静态类。

class Foo { }

namespace Foo {
    export class Bar { }
}

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

定义Foo.prototype.Bar(非静态)

要创建无缝的非静态嵌套类,可以使用prototype来指示嵌套类不是静态的。

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()
  • 注意:调用new Foo.prototype.Bar()不起作用,尽管它是有效的Typescript,即使没有类型声明。
6qftjkof

6qftjkof6#

我希望这能有所帮助

能够:

  • 创建新的内部类示例
  • 访问外部类示例/原型成员
  • 实现接口
  • 使用装饰器
    用例
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

相关问题