打字稿:使用静态内部class的类型
Typescript: Using the type of a static inner class
我正在尝试编写一个 class 向其消费者公开内部数据结构,class 本身将使用的数据结构。
示例:
class Outer {
static Inner = class {
inInner: number
};
constructor(public inner: Outer.Inner) { }
}
这里的问题是 Outer.Inner
没有被识别为类型。
我找到的唯一答案是 workarounds (in Typescript playground)。我想知道是否有任何优雅的方法可以做到这一点。
用例:
我有一堆在客户端和服务器之间通过 WebSockets 发送的动作。每个 Action
都有自己的 Data
内部 class。 Data
class 本身在服务器的其他地方使用。我可以将其分成两个 classes(或接口),例如 Action1
、Action1Data
,但我认为 Action1.Data
是一个更具可读性的设计。
您的第二个“解决方法”是首选方法:
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”的概念。
请记住,class
语法只是 es5 原型继承的糖分。
你会如何在原型继承中表示内部 class ?你把它作为一个实例变量吗?或低于 Outer.prototype.???
它在 es5 中的结果是这样的:
var Outer = function Outer(...) { ... }
Outer.Inner = function Inner() { ... }
如果你看一下,Outer.Inner
中的 Outer
只是作为一个“命名空间”来保存 Inner
class.
我找到了一个更好的解决方法,它甚至允许内部 class 访问外部 class 的私有成员,就像您在类 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 来将装饰器放在 class 上,我们最终得到一个功能齐全的真实内部 class:
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;
}
我正在尝试编写一个 class 向其消费者公开内部数据结构,class 本身将使用的数据结构。
示例:
class Outer {
static Inner = class {
inInner: number
};
constructor(public inner: Outer.Inner) { }
}
这里的问题是 Outer.Inner
没有被识别为类型。
我找到的唯一答案是 workarounds (in Typescript playground)。我想知道是否有任何优雅的方法可以做到这一点。
用例:
我有一堆在客户端和服务器之间通过 WebSockets 发送的动作。每个 Action
都有自己的 Data
内部 class。 Data
class 本身在服务器的其他地方使用。我可以将其分成两个 classes(或接口),例如 Action1
、Action1Data
,但我认为 Action1.Data
是一个更具可读性的设计。
您的第二个“解决方法”是首选方法:
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”的概念。
请记住,class
语法只是 es5 原型继承的糖分。
你会如何在原型继承中表示内部 class ?你把它作为一个实例变量吗?或低于 Outer.prototype.???
它在 es5 中的结果是这样的:
var Outer = function Outer(...) { ... }
Outer.Inner = function Inner() { ... }
如果你看一下,Outer.Inner
中的 Outer
只是作为一个“命名空间”来保存 Inner
class.
我找到了一个更好的解决方法,它甚至允许内部 class 访问外部 class 的私有成员,就像您在类 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 来将装饰器放在 class 上,我们最终得到一个功能齐全的真实内部 class:
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;
}