与构造签名的接口不是类型检查

时间:2012-10-18 10:12:53

标签: typescript

我一直在使用TypeScript中的构造签名接口,当下面的键盘检查失败时我感到有点困惑:

class Foo {
    constructor () {
    }
}

interface Bar {
    new(): Bar;
}

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

var o = Baz(Foo);

类型错误是:

  

提供的参数与调用目标的任何签名都不匹配:   构造类型'new()=>的签名Foo'和'Bar'是   不兼容:类型'Bar'需要构造签名,但Type   'Foo'缺少一个(C:Bar)=>杆

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

5 个答案:

答案 0 :(得分: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);

答案 1 :(得分:1)

问题(至少从TypeScript编译器的角度来看)是Bar的{​​{1}}方法的签名。如果您使用以下内容替换new的定义,

Bar

它有效。您也可以使用interface Bar { new (): any; } ,只使用new (): Foo,因为返回值不起作用。

答案 2 :(得分:1)

我想我知道你在哪里采取这种做法,我认为你需要一种微妙的不同方法。

此示例说明如下:

  • Baz 必须传递可更新的项目。
  • Baz 返回一个栏
  • 并非所有Bar都需要新的,只有那些被传递给Baz

以下是示例:

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,而不是一个新的。 / p>

答案 3 :(得分: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);

在上面的例子中变量&#34; o&#34;将被推断为Foo类型。

答案 4 :(得分:0)

真的有一个简单的答案。查看您的Bar界面:

interface Bar {
    new(): Bar;
}

比方说,您已经成功创建了一些实现该接口的Magic类。

class Magic implements Bar {
    // ...
}

这意味着Magic的任何实例都必须遵守Bar的规范。因此,假设您有一个名为Magic的{​​{1}}实例。

由于magic符合magic的规范,因此Bar必须是可更新的,这意味着以下各项必须有效:

magic

此外,该调用的结果即const foo = new magic() // lowercase m! 必须本身遵守foo。这意味着以下内容也必须起作用:

Bar

然后很明显,以下内容也必须起作用:

const zzz = new foo();

很明显,您的代码不满足此条件。因此,您的代码不会键入check。