#typescript #.d.ts
#typescript #.d.ts
Вопрос:
Я заполняю объявление модуля сторонней библиотеки JS, и библиотека содержит подклассы, которые (по подсчетам Typescript) несовместимо переопределяют методы родительского класса. Существует много примеров этого, но простой пример следующий:
Базовый класс:
class Entity {
...
/**
* Test whether a given User has permission to perform some action on this Entity
* @param {User} user The User requesting creation
* @param {string} action The attempted action
* @return {boolean} Does the User have permission?
*/
can(user, action) {
...
}
}
Подкласс:
class User extends Entity {
...
/**
* Test whether the User is able to perform a certain permission action. Game Master users are always allowed to
* perform every action, regardless of permissions.
*
* @param {string} permission The action to test
* @return {boolean} Does the user have the ability to perform this action?
*/
can(permission) {
...
}
}
Как я могу точно представить переопределенные методы, подобные приведенным выше, без указания tsc на очевидное? Или мне придется каким-то образом «лгать» и искажать связь между Entity
и User
?
Комментарии:
1.Судя по представленному коду,
User
не является подклассомEntity
…2. @spender Спасибо, исправлено. Я вручную набрал усеченный код для этого вопроса.
Ответ №1:
Вы можете создать тип, который удаляет can
свойство из базового Entity
типа, а затем присваивает Entity
переменной этого типа.
Теперь вы можете создать новый класс, производный от этой переменной-ссылки на «класс».
Это нарушает полиморфизм (как и первоначальный разработчик). Это ужасно. Не делайте этого. Стисни зубы и реорганизуй свой беспорядок.
class Entity {
can(user: string, action: string) {
console.log(user, action)
}
}
type PartialEntity = new () => { [P in Exclude<keyof Entity, 'can'>]: Entity[P] }
const EntityNoCan: PartialEntity = Entity;
class User extends EntityNoCan {
can(permission: number) {
console.log(permission)
}
}
Комментарии:
1. Как бы вы порекомендовали мне провести рефакторинг «моего беспорядка»? Или ты обращаешься на королевское «ты»?
2. Что ж, похоже, вы унаследовали дизайн, который злоупотребляет слабой природой наследования JavaScript. Используя такой подход, созданные объекты нарушают принцип подстановки Лискова, сводя на нет весь смысл наследования. Это недостаток в базовом дизайне, который на моем месте я бы сделал крюк, чтобы исправить.
Ответ №2:
Похоже, что a // @ts-ignore
— действительно единственный вариант здесь. Другое предлагаемое решение неприменимо к объявлениям типов.