У меня возникли проблемы с использованием системы типов TypeScript для моделирования универсального интерфейса для вызова из Lua в TypeScript. Чтобы это работало, разработчик должен определить интерфейс TypeScript, определяющий методы TypeScript, к которым может обращаться Lua. Детали здесь не имеют большого значения, так как приведенный ниже простой пример иллюстрирует мое замешательство.
Как видно из приведенного выше кода, у меня есть «ApiInterface», который определяет произвольные методы, которые разработчик может захотеть вызвать из Lua. Все такие методы принимают первый аргумент, который является объектом (похожим на «это»), а остальные аргументы могут быть любыми, которые разработчику нужно передать из Lua в метод TypeScript. На практике единственными типами, поддерживаемыми для этих оставшихся аргументов, являются примитивы, такие как число, строка, логическое значение, нуль. В приведенном выше примере кода я определил 3 таких метода API, но разработчик может определить любые методы по своему усмотрению. Весь смысл этого модуля Lua-to-TypeScript в том, чтобы быть универсальным и не привязанным к какому-либо конкретному определению «ApiInterface».
В конечном итоге среда выполнения упаковывает вызов метода Lua-to-TypeScript в объект типа ApiCall, который, как вы можете видеть, определен с полями для имени метода, объектом JavaScript, используемым для «этого», и оставшимися произвольными аргументами.
Чтобы проиллюстрировать мое замешательство, я показал KeyofDemo, чтобы проиллюстрировать ошибку TypeScript, которую я получаю. В классе KeyofDemo есть метод run, который хочет получить объект ApiCall и вызвать соответствующую функцию TypeScript/JavaScript.
Вы можете увидеть красную волнистую линию под фактическим вызовом метода в двух случаях. В одном случае нет дополнительных аргументов (помимо обязательного аргумента this), а в другом случае ApiCall.args фактически заполняется массивом аргументов для передачи из Lua в TypeScript.
Сообщение об ошибке из первого случая с красными волнистыми линиями: A spread argument must either have a tuple type or be passed to a rest parameter
.
Сообщение об ошибке из второго случая с красными волнистыми линиями: Expected 3 arguments but got 1
.
Ни одно из этих сообщений об ошибках не имеет для меня никакого смысла. Если я попытаюсь скомпилировать приведенный выше код TypeScript, компилятор сообщит об аналогичных ошибках.
Как я могу заставить систему типов TypeScript наилучшим образом моделировать поведение, которое я описал? На данный момент я обошел эту проблему, изменив строки 23 и 25 для регистра «this.api» на «любой», и это закрывает компилятор TypeScript. Но я хотел бы знать, как правильно смоделировать эту проблему.
Первая ошибка связана с тем, что Javascript/Typescript не поддерживает использование операторов расширения в параметрах, если ваша функция не настроена для этого.
Вы должны настроить функцию для приема переменных параметров.
interface ApiInterface {
apiMethod0(thisObj: Object, ...args: any[]): void
apiMethod1(thisObj: Object, ...args: [string]): void
apiMethod2(thisObj: Object, ...args: [number, boolean]): void
}
Смотрите этот код на игровой площадке
Вторая ошибка заключается в том, что все методы должны иметь одинаковую «форму» или иметь одинаковое количество параметров. В этом случае мы убиваем обоих зайцев одним камнем.
Хорошо, спасибо за объяснение - имеет смысл. Я был сбит с толку, потому что Javascript разрешает оператор распространения в этой ситуации; это Typescript запрещает это во имя безопасности типа параметра. Предложенные выше изменения в ApiInterface действительно удовлетворяют Typescript, но они представляют собой неудобный способ для будущих разработчиков определять свои функции Typescript. Это может быть менее запутанным для будущих разработчиков, которым придется определять для меня новые ApiInterfaces, чтобы реализация использовала приведение к «любому», что позволяет определять ApiInterface более интуитивно понятным способом.
Укажите свой код как текст не в виде изображения. Чтобы действительно помочь любому, кто решит ответить, также ссылка на код в машинописная площадка увеличит ваши шансы на получение хорошего ответа.