【问题标题】:Can you create nested classes in TypeScript?你可以在 TypeScript 中创建嵌套类吗?
【发布时间】:2015-12-06 06:51:35
【问题描述】:

有没有办法在 TypeScript 中嵌套类。例如。我想像这样使用它们:

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

【问题讨论】:

  • 对于较旧的 typescript (Any way to nest classes in typescript?

标签: javascript typescript


【解决方案1】:

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

class Foo {
    static Bar = class {
        
    }
}

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

【讨论】:

  • 此示例在 Typescript 1.6.3 中不起作用:错误 TS4028 导出类的公共静态属性“Bar”具有或正在使用私有名称“(匿名类)”。
  • @Sergey 我遇到了同样的问题,所以按照我下面的回答开始使用命名空间。
  • 有没有办法在类中创建接口?即,如果我们希望 Bar 是一个界面
  • @LittaHervi - 一个用例是从例如工厂方法返回外部接口的私有实现。 Java(和其他)的另一个例子是迭代器,它需要对其包含类的成员变量进行特权访问,并通过范围规则自动执行此操作,但您永远不希望这些被直接导出和实例化。
  • 有什么方法可以重用父类中的嵌套类?类 Foo { 静态栏 = 类 { };字段A:酒吧; //不起作用:找不到名称“Bar”字段B:Foo.Bar; //不起作用:'Foo' 仅指一种类型,但在这里用作命名空间。 } // 有效! var foo = new Foo(); var bar = new Foo.Bar();
【解决方案2】:

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

它允许内部类访问外部类的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

【讨论】:

  • @RyanCavanaugh 访问“内部”类表达式中的私有成员的能力是错误​​吗?
  • 我在 TypeScript 团队中验证了这是正确的用法。 github.com/Microsoft/TypeScript/issues/…
  • 是否可以在不直接传递的情况下访问父上下文?
  • @shabunc 据我所知
  • 如果你需要一个“真正的”(不是“静态的”)内部类(作为对象模板),然后像() => new class一样使用它
【解决方案3】:

如果没有收到编译错误,我无法让它与导出的类一起使用,而是使用namespaces

namespace MyNamespace {
    export class Foo { }
}

namespace MyNamespace.Foo {
    export class Bar { }
}

【讨论】:

  • 相同。 'Foo' 仅指一种类型,但在这里用作命名空间。
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

    这个答案是关于 TypeScript 中的一个无缝嵌套类实现,它建立在 @basarat 的答案之上。

    要使 static 嵌套类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()
    

    【讨论】:

      【解决方案6】:

      希望对你有帮助

      能够:

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

      用例

      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
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-29
        • 2011-04-04
        • 1970-01-01
        • 2016-09-13
        • 2023-02-11
        • 1970-01-01
        • 1970-01-01
        • 2011-01-18
        相关资源
        最近更新 更多