Как заставить класс реализовать подпись вызова в Typescript?
Я определил следующий интерфейс в машинописи:
interface MyInterface {
() : string;
}
Этот интерфейс просто вводит сигнатуру вызова, которая не принимает параметров и возвращает строку. Как мне реализовать этот тип в классе? Я пробовал следующее:
class MyType implements MyInterface {
function () : string {
return "Hello World.";
}
}
Компилятор постоянно говорит мне, что
Класс "MyType" объявляет интерфейс "MyInterface", но не реализует его: для типа "MyInterface" требуется подпись вызова, а для типа "MyType" ее нет.
Как я могу реализовать подпись вызова?
3 ответа
Классы не могут соответствовать этому интерфейсу. Я думаю, что ближе всего можно получить этот класс, который будет генерировать код, функционально соответствующий интерфейсу (но не в соответствии с компилятором).
class MyType implements MyInterface {
constructor {
return "Hello";
}
}
alert(MyType());
Это создаст рабочий код, но компилятор будет жаловаться, что MyType
не вызывается, потому что имеет подпись new() = 'string'
(даже если вы называете это с new
, он вернет объект).
Чтобы создать что-то, что действительно соответствует интерфейсу без компиляции, компилятор должен сделать что-то вроде этого:
var MyType = (() : MyInterface => {
return function() {
return "Hello";
}
})();
alert(MyType());
В случае, если вызываемый интерфейс должен иметь другие методы, вы можете сделать это следующим образом:
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.setName('Dolly');
greeter(); // prints 'Hello Dolly!'
Даунсайд: greeter instanceof ConsoleGreeter
является false
Примеры кода в этом ответе предполагают следующее объявление:
var implementation: MyInterface;
Обеспечение реализации вызываемого интерфейса
В качестве продолжения принятого ответа, как предлагают некоторые из его комментаторов, функция, которая соответствует сигнатуре вызова интерфейса, неявно реализует интерфейс. Таким образом, вы можете использовать любую подходящую функцию в качестве реализации.
Например:
implementation = () => "Hello";
Вам не нужно явно указывать, что функция реализует интерфейс. Однако, если вы хотите быть явным, вы можете использовать приведение:
implementation = <MyInterface>() => "Hello";
Предоставление многоразовой реализации
Если вы хотите создать многократно используемую реализацию интерфейса, как это обычно делается с интерфейсом Java или C#, просто сохраните функцию где-нибудь доступной для ее потребителей.
Например:
function Greet() {
return "Hello";
}
implementation = Greet;
Предоставление параметризованной реализации
Возможно, вы захотите иметь возможность параметризовать реализацию так же, как вы можете параметризовать класс. Вот один из способов сделать это:
function MakeGreeter(greeting: string) {
return () => greeting;
}
implementation = MakeGreeter("Hello");
Если вы хотите, чтобы результат был напечатан как интерфейс, просто явно установите тип возвращаемого значения или приведите возвращаемое значение.