10

我一直在使用 TypeScript 中带有构造签名的接口,当以下类型检查失败时,我变得有点困惑:

class Foo {
    constructor () {
    }
}

interface Bar {
    new(): Bar;
}

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

var o = Baz(Foo);

类型错误是:

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

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

4

5 回答 5

5

这是您的代码的更新版本,有细微的变化。

Bar我们用我们期望出现的任何函数和变量来定义接口。

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

因为Foo实现Bar并具有构造函数并且Baz需要 a 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);
于 2012-10-18T11:18:14.557 回答
2

问题(至少从 TypeScript 编译器的角度来看)是Bar'new方法的签名。如果将 的定义替换为Bar以下内容,

interface Bar {
  new (): any;
}

有用。您不妨使用new (): Foo,就像Bar返回值不起作用一样。

于 2012-10-18T10:26:48.033 回答
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 类型。

于 2014-08-14T04:26:18.880 回答
1

我想我知道你在做什么,我认为你需要一种微妙不同的方法。

这个例子说明了以下内容:

  • Baz必须传递一个新的项目。
  • Baz返回一个 Bar
  • 不是所有的 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 而不是 newable。

于 2012-10-18T14:51:11.320 回答
0

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

interface Bar {
    new(): Bar;
}

假设您已经设法创建了一些Magic实现此接口的类。

class Magic implements Bar {
    // ...
}

这意味着任何实例都Magic必须遵守Bar. 所以假设你有一个Magic被调用的实例magic

由于magic遵守 的规范Barmagic必须是可更新的,这意味着以下必须工作:

const foo = new magic() // lowercase m!

此外,该调用的结果,即foo本身必须遵守Bar。这意味着以下内容也必须有效:

const zzz = new foo();

然后很明显,以下内容也必须有效:

new (new (new (new (new (new (new (new Magic())))))))

很明显,您的代码不满足此条件。因此,您的代码不会进行类型检查。

于 2020-04-02T20:04:13.073 回答