Чтобы выразить класс в типе, вам нужна подпись конструктора:
interface ProfessionRankingMap {
// The implementer must have a constructor with no args that returns Profession
top1ProfessionType: new () => Profession
top2ProfessionType: new () => Profession
}
const classAProfessionRankingMap: ProfessionRankingMap = {
top1ProfessionType: Engineer,
top2ProfessionType: Doctor
}
Ссылка на игровую площадку
Если мы хотим принимать классы с конструкторами, которые имеютлюбое количество аргументов, которые мы можем использовать new (... args:any[]) => Profession
.
Вторая часть вашей проблемы немного сложнее.Typescript использует структурную типизацию для определения совместимости типов.Таким образом, структура класса имеет значение, а не предложение implements
.Предложение implements
просто поможет вам сообщать об ошибках при объявлении класса, гарантируя, что в нем есть все необходимые члены, поэтому вы получаете ошибки раньше, чем когда пытаетесь использовать класс, где ожидается интерфейс.
Это означает, что до тех пор, пока Doctor
имеет всех членов Profession
, невозможно предотвратить его передачу туда, где ожидается Profession
.
Единственное решение - использоватьабстрактный класс с приватным членом.Закрытый член гарантирует, что никакие другие классы, кроме тех, которые расширяют абстрактный класс, не будут совместимы с типом абстрактного класса:
abstract class Profession {
private _notStructural: undefined;
abstract work(): void
}
class Engineer extends Profession {
work() { }
}
class Doctor {
work() { }
}
interface ProfessionRankingMap {
top1ProfessionType: new () => Profession
top2ProfessionType: new () => Profession
}
const classAProfessionRankingMap: ProfessionRankingMap = {
top1ProfessionType: Engineer,
top2ProfessionType: Doctor // error
}
Ссылка для игровой площадки