2012-10-18 16 views
9

我已经打了一下,有接口,以构建签名的打字稿,和我有点困惑时,以下没有类型检查:接口,以构建签名不是类型检查

class Foo { 
    constructor() { 
    } 
} 

interface Bar { 
    new(): Bar; 
} 

function Baz(C : Bar) { 
    return new C() 
} 

var o = Baz(Foo); 

类型错误:

提供的参数不匹配,通话对象的任何签名: 构造类型的“新的()=>富”和“酒吧”是 不兼容的签名:类型“酒吧”需要一个结构特征,但类型 '富'缺乏(C:Bar)=> Bar

Foo构造函数的类型是()=> Foo,这就是我认为的Bar说的。我在这里错过了什么吗?

回答

1

问题(至少从TypeScript编译器的角度来看)是Barnew方法的签名。如果您要更换的Bar用下面的定义,

interface Bar { 
    new(): any; 
} 

它的工作原理。你不妨使用new(): Foo,只是Bar作为返回值不起作用。

5

以下是您的代码的更新版本,其中包含一些细微变化。

我们定义了Bar接口,它带有我们期望存在的任何函数和变量。

接下来,我们扩展Bar接口与NewableBar接口。这只是定义了一个返回Bar的构造函数。

由于Foo实现了Bar并且有一个构造函数,并且Baz需要NewableBar,所有内容都会被检查。

这比any稍微冗长一些 - 但会给你所需的检查。

interface Bar { 

} 

interface NewableBar extends Bar { 
    new(); 
} 

class Foo implements Bar { 
    constructor() { 

    } 
} 

function Baz(C : NewableBar) { 
    return new C() 
} 

var o = Baz(Foo); 
+0

而不是使用'any'你使用超级接口(你可以省略'implements'和'extends',btw)。没错,我猜,并且比'any'更好,但有一件事仍然让我感到困惑:为什么你不能让'NewableBar :: new()'返回一个'NewableBar'?为什么它必须是一个比'NewableBar'更通用的类型(显然至少与'Foo'一样)? –

+0

@AdrianLang我把明确的继承和实现放在明确的位置,但你是正确的 - 如果一切都匹配,TypeScript会很乐意推断这些。尝试将方法上的new()签名视为特定类型时存在解释问题。 – Fenton

+0

但是,只要您尝试向Foo添加任何内容,就会中断。 编辑:对不起,我做错了。我的结构签名应该是:'new(... _:any []):Bar;' – farre

1

我想我知道你在哪里接受这个,我认为你需要一个微妙不同的方法。

这个例子说以下内容:

  • 巴兹必须传递是newable的项目。
  • 巴兹返回酒吧
  • 并非所有酒吧的需要是newable,只有那些被传递给巴兹

这里是例子:

interface Bar { 
    sayHello(name: string): void; 
} 

interface Newable { 
    new(); 
} 

class Foo implements Bar { 
    constructor() { 

    } 

    sayHello(name: string) { 
     window.alert('Hello ' + name); 
    } 
} 

function Baz(C : Newable) { 
    return <Bar> new C() 
} 

var o = Baz(Foo); 
o.sayHello('Bob'); 

这样做的唯一的危险方法是你可以将不是Bar的新东西传递给Baz函数。当你通过从一个参数创建一个对象来使用动态特性时,除非你愿意传入一个预先初始化的对象,否则这基本上是不可避免的,在这种情况下,Baz会非常高兴地接受一个Bar,而不是一个新的对象。

+0

是的,沿着这些路线是我想达到的。除了我想将“Bar”和“Newable”作为一个接口。谢谢。 – farre

1

我知道这是一个古老的问题,但我今天有类似的需求,并遇到帖子。一些试验和错误后,我想出了以下解决方案:

interface Bar { 
    sayHello(name: string); 
} 

class Foo implements Bar { 
    sayHello(name: string) { 
     window.alert("Hello " + name); 
    } 
} 

function Baz(c: new() => Bar) { 
    return new C(); 
} 

var o = Baz(Foo); 
o.sayHello("Bob"); 

基本接口只能定义一个对象实例的合同,所以需要一定的构造存在必须在将成为函数来完成调用构造函数。这种方法在泛型上也很好玩:

function Baz<T extends Bar>(c: new() => T) { 
    return new c(); 
} 

var o = Baz(Foo); 

在上面的例子中,变量“o”将被推断为类型Foo。