我在typescript中定义了以下接口:
interface MyInterface {
() : string;
}
此接口简单地引入了一个不带参数的调用签名并返回一个字符串。如何在类中实现此类型?我尝试过以下方法:
class MyType implements MyInterface {
function () : string {
return "Hello World.";
}
}
编译器一直告诉我
类'MyType'声明接口'MyInterface'但未实现它:Type'MyInterface'需要调用签名,但Type'MyType'缺少一个
如何实施呼叫签名?
答案 0 :(得分:12)
类与该接口不匹配。你能得到的最接近的,我认为是这个类,它将生成与接口功能匹配的代码(但不是根据编译器)。
class MyType implements MyInterface {
constructor {
return "Hello";
}
}
alert(MyType());
这将生成工作代码,但编译器会抱怨MyType
不可调用,因为它具有签名new() = 'string'
(即使你用new
调用它,它也会返回一个东西)。
要在没有编译器抱怨的情况下创建与界面完全匹配的内容,您必须执行以下操作:
var MyType = (() : MyInterface => {
return function() {
return "Hello";
}
})();
alert(MyType());
答案 1 :(得分:6)
本回答中的代码示例假设以下声明:
var implementation: MyInterface;
作为the accepted answer的后续行动,正如其评论员所建议的那样,与接口的调用签名匹配的函数隐式实现了接口。因此,您可以使用任何匹配函数作为实现。
例如:
implementation = () => "Hello";
您无需明确指定该函数实现该接口。但是,如果您想要明确,可以使用强制转换:
implementation = <MyInterface>() => "Hello";
如果您想像通常使用Java或C#接口那样生成可重用的接口实现,只需将该功能存储在其消费者可访问的位置。
例如:
function Greet() {
return "Hello";
}
implementation = Greet;
您可能希望能够以与参数化类相同的方式参数化实现。这是一种方法:
function MakeGreeter(greeting: string) {
return () => greeting;
}
implementation = MakeGreeter("Hello");
如果要将结果键入为接口,只需显式设置返回类型或转换返回的值。
答案 2 :(得分:2)
如果可调用接口应该有其他方法,你可以这样做:
interface Greeter {
(): void;
setName(name: string): void;
}
class ConsoleGreeter {
private constructor( // constructable via `create()`
private name = 'world'
) {}
public call(): void {
console.log(`Hello ${this.name}!`);
}
public setName(name: string) {
this.name = name;
}
public static create(): Greeter {
const instance = new ConsoleGreeter();
return Object.assign(
() => instance.call(),
{
setName: (name: string) => instance.setName(name)
// ... forward other methods
}
);
}
}
const greeter = ConsoleGreeter.create();
greeter(); // prints 'Hello world!'
greeter.setName('Dolly');
greeter(); // prints 'Hello Dolly!'
下行:greeter instanceof ConsoleGreeter
为false