Typescript:使用静态内部类的类型

Posted

技术标签:

【中文标题】Typescript:使用静态内部类的类型【英文标题】:Typescript: Using the type of a static inner class 【发布时间】:2017-03-17 18:00:26 【问题描述】:

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

例子:

class Outer 
    static Inner = class 
        inInner: number
    ;

    constructor(public inner: Outer.Inner)  

这里的问题是Outer.Inner没有被识别为类型。

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


用例:

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

【问题讨论】:

【参考方案1】:

您的第二个“解决方法”是首选方法:

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 原型继承的糖。 您将如何表示原型继承中的内部类?你把它作为一个实例变量吗?或下Outer.prototype.???

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

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

如果您看一下,Outer.Inner 中的Outer 仅用作保存Inner 类的“命名空间”。

【讨论】:

感谢 Typescript 手册参考!我没有意识到命名空间可以正式用于声明合并。 我使用您提供的解决方案。但是,有一个问题。假设 Outer 类在 ES6 模块中并被导出。但是我们不想导出 Outer.Inner。有可能吗? 由于Inner被用于Outer的公共属性中,所以需要将其公开。这个命名空间技巧通过将***类型隐藏在Outer 下来帮助最小化***类型。如果你真的不想暴露它,你可以考虑直接内联你的类型。但也有限制。 这不满足内部类为私有时的情况。 @TomaszGawel 是的,但是如果该类确实是私有的,则不需要公开它。做Outer.Inner = 就是暴露它。【参考方案2】:

我找到了一个更好的解决方法,它甚至允许内部类访问外部类的私有成员,就像您在类 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;

【讨论】:

你也可以使用export type Inner = InstanceType<typeof Outer.Inner>;

以上是关于Typescript:使用静态内部类的类型的主要内容,如果未能解决你的问题,请参考以下文章

静态类和内部类的区别是啥

一个java内部类有几个分类?

Java 枚举类型必须定义在静态类中

内部类和匿名内部类的用法

java内部类的静态嵌套类

java内部类可以访问外部类的静态方法吗