我目前正在研究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)
),我的目标是分别记录它们。
答案 0 :(得分:3)
那这样的事情呢?
declare class Animal
{
constructor ( type )
static Dog : (new () => Animal)
}
由于存在重载的构造函数,因此键入有所不同:
declare class Animal
{
constructor ( type )
static Dog : (new () => Animal) & (new (color) => Animal)
}
答案 1 :(得分:0)
由于您是子类化,所以保持整洁简洁非常重要。按照上面的方式,您可以看到Dog是一种动物,但与动物没有什么区别。在某些情况下,某些变量或方法会被覆盖。话虽如此,如果您实施类似于以下内容的方法,我会发现更好:
class Animal {
constructor(){}
communicate() { return "Makes Noise"; }
}
class Dog extends Animal {
constructor(){
super();
}
communicate() { return "Barks"; }
}
从那里您可以覆盖方法或变量,以正确区分Dog和Animal以及其他Animal子类。