Я не уверен, что я сейчас описываю квесты в заголовке.
То, что я пытаюсь спросить, вытекает из следующего требования.
Я пытаюсь сделать реферат для состояний конечных автоматов и предлагает следующее определение (в машинописном тексте)
interface IState {
send<T, E>(message: T, callback?:(event: E)=>void): IState;
}
Я пытаюсь выразить, что состояние конечного автомата должно быть способным принимать сообщения и возвращать новое состояние с необязательным обратным вызовом для обработки событий s во время перехода.
При реализации этого интерфейса в конкретных состояниях возникает проблема.
Например, я пытаюсь создать простой конечный автомат только с двумя состояниями ВЛЕВО и ВПРАВО с тремя возможными сообщениями go-on , повернуть налево , повернуть направо . Следующая таблица показывает их отношения.
Ключевым моментом является то, что я хочу ограничить состояние ВЛЕВО принимать только Продолжить и Повернуть направо сообщения при отправке Повернуть- осталось до ВЛЕВО , как ожидается, будет ошибка компиляции .
Я пытался реализовать подобное в машинописи 3.4.5.
class Left implements IState {
send(m: 'go-on', cb?: (e: never) => void): Left;
send(m: 'turn-right', cb?: (e: never) => void): Right;
send(m: 'go-on' | 'turn-right', cb?: any) {
return m === 'go-on' ? new Left() : new Right();
}
}
class Right implements IState {
send(m: 'go-on', cb?: (e: never) => void): Right;
send(m: 'turn-left', cb?: (e: never) => void): Left;
send(m: 'go-on' | 'turn-left', cb?: any) {
return m === 'go-on' ? new Right() : new Left();
}
}
Реализация не имеет ошибки компиляции, а автозаполнение работает как положено. Но так как это выглядит странно, я задал вопрос Универсальная функция TypeScript может работать только для перегрузки функции с более чем одной подписью .
Спасибо за добрые ответы на этот вопрос, я понимаю, что присваивать функции перегрузки универсальным функциям неправильно. Но тогда как я могу выразить общий интерфейс состояния, сохраняя при этом определенное состояние, принимая только нужные типы сообщений?
связанная проблема GitHub
Еще одна абстракция, которую я могу придумать, это
interface IState<T, E, R extends IState<?, ?, ?>> {
send(message: T, callback?:(event: E)=>void): R;
}
Но возвращаемый тип рекурсивный, и я не знаю, что заполнить для этих трех квестовых отметок выше.
Более простая версия может быть
interface IState<T, E> {
send(message: T, callback?:(event: E)=>void): IState<any, any>;
}
Кажется, что он ведет себя так, за исключением раздражающего any в типе возврата.
interface IState {
send<T, E>(message: T, callback?:(event: E)=>void): IState;
}
Я нашел , возможно, связанную проблему в GitHub по поводу общего значения .
Этот вопрос хорошо определен?
Если true, есть ли правильное решение в списке методов выше?
Если false, какое правильное решение?