特定javascript实例化模式的正确类型脚本定义是什么

特定javascript实例化模式的正确类型脚本定义是什么,javascript,typescript,new-operator,instantiation,typescript-definitions,Javascript,Typescript,New Operator,Instantiation,Typescript Definitions,我目前正在处理Paper.jslibrary typescript定义,我很难找到正确的方法来记录API的某些部分 这种情况可以简化为以下情况:假设我们有一个Animal类,它有一个静态属性Dog,用作该类的自定义构造函数: var Animal = function(type) {}; Animal.Dog = function() { return new Animal('dog'); }; Animal实例可以通过两种方式构建: var dog = new Animal('dog

我目前正在处理
Paper.js
library typescript定义,我很难找到正确的方法来记录API的某些部分

这种情况可以简化为以下情况:假设我们有一个
Animal
类,它有一个静态属性
Dog
,用作该类的自定义构造函数:

var Animal = function(type) {};
Animal.Dog = function() {
    return new Animal('dog');
};
Animal
实例可以通过两种方式构建:

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)
),我的目标是分别记录它们。

类似这样的东西怎么样:

declare class Animal
{
    constructor ( type )
    static Dog : (new () => Animal)
}
编辑 由于存在重载构造函数,因此类型略有不同:

declare class Animal
{
    constructor ( type )
    static Dog : (new () => Animal) & (new (color) => Animal)
}

因为您是子类化的。。保持事物的整洁和简洁是很重要的。按照上面写的方式,你可以看到狗是由动物创造的,但它和动物没有区别。在某些情况下,有些变量或方法被重写。话虽如此,我发现如果您实施类似于以下内容的内容会更好:

class Animal {
  constructor(){}
  communicate() { return "Makes Noise"; }
}

class Dog extends Animal {
  constructor(){
    super();
  }

  communicate() { return "Barks"; }
}

从那里,您可以重写方法或变量,以便正确区分狗与动物、与其他动物子类。

在最后一个示例中,我相信您可以通过
var Dog:Animal=new Animal.Dog()强制使用动物类型@dotconnor-您可以,但这会给维护带来危险。你必须记住每次都这样做。不使用
new
关键字怎么样?或者,如果你经常混淆狗和动物,这是否太令人困惑了?@dotconnor——例如,这是由Paper.js而不是OP决定的。(我个人认为,通过
new
记录这一点是不好的做法,但他们确实如此……@t-j-crowder,是的,这正是问题所在:)。我的目标是按原样为API创建类型定义。即使它的某些部分看起来很奇怪……是的,它比我的实际解决方案要好得多,因为它不需要额外的名称空间声明!非常感谢。通过试验,我发现我的问题比我最初要求的要大一些:在我的情况下,静态构造函数可以有多个签名,例如和。你知道我如何将你的想法扩展到这种情况吗?你可以将参数传递给构造函数。因此,对于Shape.Circle方法,类型是:静态圆:(new(obj:object)=>Shape)和(new(radius:number,center:number)=>Shape);这正适合这种类型,谢谢。唯一的交易是所有签名只能有一条评论,但我想这是个小问题。谢谢你的回答,但我认为你误解了这个问题。所有的要点是,我必须为
JavaScript
特定的实现创建一个类型定义,该实现不使用子类,并且
Dog
类没有意义
Animal.Dog
只是一个静态方法,用于以快捷方式实例化
Animal
类。您提议的定义实际上不允许执行
var dog=new Animal.dog()这就是我想要做的…我试图为您理解这个问题,我没有看到不进行子类化的要求,因为我上面的实现,狗就是动物。既然您说animal是一个类,而不是一个容器,那么它就意味着子类化,因为会涉及到一些方法,而且您不需要将一个子定义与父对象耦合。这一切都很好,np。
class Animal {
  constructor(){}
  communicate() { return "Makes Noise"; }
}

class Dog extends Animal {
  constructor(){
    super();
  }

  communicate() { return "Barks"; }
}