打字稿:使用静态内部类

时间:2017-03-17 18:00:26

标签: typescript inner-classes

我正在尝试编写一个向其使用者公开内部数据结构的类,这是一个类本身将使用的数据结构。

示例:

class Outer {
    static Inner = class {
        inInner: number
    };

    constructor(public inner: Outer.Inner) { }
}

此处的问题是Outer.Inner未被识别为类型。

我找到的唯一答案是workarounds (in Typescript playground)。我想知道是否有任何优雅的方法。

USECASE:

我有一堆通过WebSockets在客户端和服务器之间发送的动作。每个Action都有自己的Data内部类。 Data类本身在服务器的其他位置使用。我可以将它分成两个类(或一个接口),如Action1Action1Data,但我认为Action1.Data是一个更易读的设计。

2 个答案:

答案 0 :(得分:8)

你的第二个"解决方法"是最好的选择:

class Outer {
    constructor(public inner: Outer.Inner) { }
}

namespace Outer {
    export class Inner {
        inInner: number
    };
}

// Spec
let outer1 = new Outer({ inInner: 3 });

let outerInner = new Outer.Inner();
let outer2 = new Outer(outerInner);

TypeScript中有三种类型的声明:名称空间,类型和值。 您可以使用namespace来组织类型和值。

http://www.typescriptlang.org/docs/handbook/declaration-merging.html

它没有降低可读性,因为没有"内部类"在TypeScript中。

请记住,class语法只是es5原型继承的糖。 你如何代表原型继承的内在阶级?你把is作为实例变量吗?或在Outer.prototype.???

它在es5中的结果是这样的:

var Outer = function Outer(...) { ... }
Outer.Inner = function Inner() { ... }

如果您查看它,Outer中的Outer.Inner仅作为"命名空间"持有Inner班。

答案 1 :(得分:0)

我为此找到了一个更好的解决方法,它甚至允许内部类访问外部类的私有成员,就像您希望使用的C#语言一样。实际上,您可以使用typeof运算符轻松获取静态属性的类型。对您的示例进行的较小修改可以起作用:

class Outer
{
    static Inner = class
    {
        inInner: number = 0;
    };

    constructor(public inner: typeof Outer.Inner.prototype) { }
}

但是很快将类型称为typeof Outer.Inner.prototype变得很麻烦,因此在其下面添加即可,您可以根据需要将其简单地称为Outer.Inner

namespace Outer
{
    export type Inner = typeof Outer.Inner.prototype;
}

通过另一个变通方法将其组合起来,以使我们可以通过将装饰器设置为非匿名类来将其放置在该类上,最后得到一个功能齐全的真正内部类:

class Outer
{
    static Inner = (() =>
    {
        @decoratable()
        class OuterInner
        {
            inInner: number = 0;
        }
        return OuterInner;
    })();

    constructor(public inner: Outer.Inner) { }
}

namespace Outer
{
    export type Inner = typeof Outer.Inner.prototype;
}