【问题标题】:Any way to declare a nest class structure in typescript?有什么方法可以在打字稿中声明嵌套类结构?
【发布时间】:2012-11-09 19:30:54
【问题描述】:

我对定义现有框架 (openlayers.d.ts) 很感兴趣,但不知道如何表达 OpenLayers.Layer 既是类又是 OpenLayers.Layer.Markers 的命名空间这一事实。我相信这使 Markers 成为 Layer 的嵌套类。

用法:

l = new OpenLayers.Layer(...); // this is a base class, never do this
m = new OpenLayers.Layer.Markers(...);

如何在 typescript 中同时声明 Layer 和 Markers 类?

【问题讨论】:

标签: typescript


【解决方案1】:

目前不支持嵌套类。

http://typescript.codeplex.com/workitem/460

【讨论】:

  • 此问题已在 0.9.1.1 及更高版本中得到修复。请参阅下面的答案。
【解决方案2】:

您可以使用命名空间/类合并来获得与嵌套类等效的效果。这个例子改编自 Pro TypeScript 的第 1 章。

您执行与类和命名空间的合并,或者与函数和命名空间的合并。

在所有情况下,命名空间必须出现在类或函数之后才能进行合并。

改编的例子:

class Outer {

}

namespace Outer {
    export class Mid {

    }

    export module Mid {
        export class Inner {

        }
    }
}

var a = new Outer();
var b = new Outer.Mid();
var x = new Outer.Mid.Inner();

【讨论】:

  • 如何从 Mid 类调用方法到 Outer 类?
  • 应该把整个东西放在一个文件里吗?或者我们可以将实现与声明分开吗?
  • @jayarjo 同一公共根目录中的所有命名空间都构成一个名称。因此,如果您愿意,可以将多个文件都添加到同一个命名空间中。
【解决方案3】:

这有点晚了,但其他人可能会觉得它很有用。我就是这样骗TS来完成任务的。

declare module OpenLayers {
  interface Layer { 
   ....
  }

  interface Markers {
    ....
  }

  var Layer: {
    new(name:string, options?:any):Layer;
    prototype:Layer;
    Markers: { 
      new(params?:any):Markers;
      prototype: Markers;
    }
  }
}

var markers = new OpenLayers.Layer.Markers();

【讨论】:

  • 如何让一个名为 Layer 的变量与一个名为 Layer 的接口在同一范围内?
【解决方案4】:

这似乎已在 0.9.1.1 及更高版本中修复。您只需创建一个与要嵌套类型的类同名的模块,然后将嵌套类型放入其中。

更具体地说,这就是你的做法:

declare module a
{
    class b
    {
    }

    module b
    {
        class c
        {
        }
    }
}

var myB = new a.b();
var myC = new a.b.c();

这在使用 export 关键字在打字稿代码中嵌套类型时也有效:

export module a
{
    export class b
    {
    }

    export module b
    {
        export enum c
        {
            C1 = 1,
            C2 = 2,
            C3 = 3,
        }
    }
}

正如用户@recursive 在下面的cmets 中提到的,声明的顺序很重要。所以类定义必须位于具有嵌套类型的模块之前。

【讨论】:

  • 我无法让它工作,但后来我意识到顺序很重要。如果您先声明类,然后声明模块,这似乎才有效。反过来就不行了。
  • 如何使用 Typescript 在 Angular 项目中做到这一点?模块使用装饰器:@NgModule
  • 无论如何要在没有声明金字塔的情况下实现这一目标?
  • @jayarjo 我不知道。声明金字塔是唯一的方法。
【解决方案5】:

截至 2016 年,我想这更容易:

class A {
    static B = class { }
}

var a = new A();
var b = new A.B();

【讨论】:

  • 我得到这个编译错误Initializers are not allowed in ambient contexts with atom latest ts plugin
  • 如何在B 的方法中引用Athis 而不将其作为参数显式传递?或者这是不可能的,因为B 是静态的?我目前的解决方案是在A 上使用bFactory 方法,我可以在其中访问A 成员并将它们显式传递给B 构造函数,但我希望有一种更巧妙的方法来做到这一点。跨度>
  • @Monkpit: this 指的是a 对象,而不是A 类。您可以实例化许多as 和许多bs,每个都有自己的this。那么特定的b 怎么知道您希望它访问哪个a
  • @MarcG 因为类A 不是静态的,所以a 对象的任何实例都包含静态类B 的定义,不是吗?否则,为什么B 会被定义在A 的范围内呢?我可能完全错过了这里的重点......
  • @Monkpit:任何a 实例都包含B 类的定义,因此可以实例化bs。但是您可以在不实例化as 的情况下实例化bs,正如您在我的示例var b = new A.B(); 中看到的那样。
【解决方案6】:

为此使用 TypeScript 的 类表达式

var OpenLayers = class {
    static Layer = class {
        static Markers = class {}
    }
}

【讨论】:

  • 如果顶级对象是exported,它是否也有效?我面临以下错误:Public static property 'myprop' of exported class has or using private name '(Anonymous class)'。有什么建议吗?
  • @SayanPal 不知道你在做什么
猜你喜欢
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 2020-09-12
  • 1970-01-01
  • 2020-05-02
  • 2015-12-29
  • 2019-02-16
相关资源
最近更新 更多