特定 javascript 实例化模式的正确打字稿定义是啥
Posted
技术标签:
【中文标题】特定 javascript 实例化模式的正确打字稿定义是啥【英文标题】:What is the right typescript definition for a specific javascript instantiation pattern特定 javascript 实例化模式的正确打字稿定义是什么 【发布时间】:2019-04-22 03:36:28 【问题描述】:我目前正在处理 Paper.js
库打字稿定义,但我无法找到正确的方法来记录 API 的某些部分。
这种情况可以简化为:假设我们有一个Animal
类,它有一个静态属性Dog
,用作该类的自定义构造函数:
var Animal = function(type) ;
Animal.Dog = function()
return new Animal('dog');
;
Animal
实例可以通过两种方式构建:
var dog = new Animal('dog');
或者:
var dog = new Animal.Dog();
在这两种情况下,我都需要将dog
变量的类型推断为Animal
。
我第一次尝试:
declare class Animal
constructor ( type )
static Dog (): Animal
但是 TSLint 失败并出现错误:“只能使用 'new' 关键字调用 void 函数。”,因为 Animal.Dog()
函数返回类型是 Animal
。
如果我将Animal.Dog()
的返回类型设置为void
:
declare class Animal
constructor ( type )
static Dog (): void
TSLint 通过但我得到void
作为推断类型...
所以我尝试了另一种方法:
declare class Animal
constructor ( type )
declare namespace Animal
export class Dog extends Animal
constructor()
这样,TSLint 通过但在以下情况下:
var dog = new Animal.Dog();
dog
变量的推断类型是 Animal.Dog
,而不是我想要的 Animal
。
这不是什么大问题,因为Animal.Dog
类型扩展了Animal
,但库中没有Animal.Dog
,所以我发现这种解决方法会误导用户。
有没有人知道处理这种情况的更好方法?
编辑
详细说明@stramski 解决方案,我补充了这个问题,Animal.Dog
可以有多个签名(例如Animal.Dog()
和Animal.Dog(color)
),我的目标是分别记录它们。
【问题讨论】:
最后一个例子,相信你可以通过var dog: Animal = new Animal.Dog();
强制使用Animal类型
@dotconnor - 可以,但存在维护风险。您必须记住每次都这样做。
不使用new
关键字怎么办?或者如果你经常把 Dog 和 Animal 混为一谈,那会不会太混乱了?
@dotconnor - 这是由 Paper.js 而不是 OP 决定的,例如 Shape.Circle
。 (我个人认为记录您通过new
调用它的做法很糟糕,但他们确实......)
@t-j-crowder,是的,这正是问题所在:)。我的目标是按原样为 API 创建类型定义。即使它的某些部分看起来很奇怪......
【参考方案1】:
这样的事情怎么样:
declare class Animal
constructor ( type )
static Dog : (new () => Animal)
编辑
由于有重载的构造函数,所以打字有点不同:
declare class Animal
constructor ( type )
static Dog : (new () => Animal) & (new (color) => Animal)
【讨论】:
是的,它比我的实际解决方法要好得多,因为它不需要额外的命名空间声明!非常感谢。 对此进行实验,我发现我的问题比我最初要求的要广泛一些:在我的情况下,静态构造函数可以有多个签名,例如Shape.Circle(center, radius) 和 Shape.Circle(object)。你知道我如何将你的想法扩展到这个案例吗? 您可以将参数传递给构造函数。所以对于 Shape.Circle 方法,输入是: static Circle: (new (obj: object) => Shape) & (new (radius: number, center: number) => Shape); 这是完美的类型,谢谢。唯一的交易是所有签名只能有一个评论,但我想这是一个小问题。【参考方案2】:由于您是子类化.. 保持简洁明了很重要。在上面写的方式中,您可以看到 Dog 被创造为动物,但它与动物没有区别。在某些情况下,有一些变量或方法被覆盖。话虽如此,我发现如果你实现类似的东西会更好:
class Animal
constructor()
communicate() return "Makes Noise";
class Dog extends Animal
constructor()
super();
communicate() return "Barks";
您可以从那里重写方法或变量,以便正确区分 Dog 和 Animal 以及其他 Animal 子类。
【讨论】:
感谢您的回答,但我认为您误解了这个问题。关键是我必须为javascript
特定实现创建一个类型定义,该实现不使用子类化并且Dog
类没有意义。 Animal.Dog
只是一个静态方法,用于以快捷方式实例化 Animal
类。您提出的定义实际上不允许做var dog = new Animal.Dog();
这是我想要做的......
我试图为你理解这个问题,我没有看到没有子类化的要求,因为我上面的实现是 Dog IS-A Animal。由于您说动物是一个类,而不是一个容器,因此它暗示了子类化,因为会涉及方法,并且您不必将 1 个子定义耦合到父对象。一切都很好,np。以上是关于特定 javascript 实例化模式的正确打字稿定义是啥的主要内容,如果未能解决你的问题,请参考以下文章