Как назначить типу значение по умолчанию (generic | type | class)?
TypeScript Есть некоторый класс.
Экземпляр класса содержит ссылки на тип производный от этого класса.
// Так я пытаюсь передать классу используемый тип, при этом если не передается
// параметр типа, он должен вывести тип `Some`(сам себя).
// Установить по умолчанию не вышло.
class Some<TItem extends Some<TItem> /* = Some // error: circular default */> {
_item: TItem // должен быть либо `TItem extends Some` либо `Some`
getSibling(): TItem {
return this._item
}
getSelf(): this {
return this
}
}
const some = new Some()
some._item = some
// С этим все понятно - будет работать до любой глубины,
// но выведенный тип тоже не особо мне нравится - хотелось бы просто `Some`.
const s1 = some.getSelf().getSelf().getSelf()
// -> Some<Some<unknown>>
// А это уже ломается
const s2 = some.getSibling().getSibling().getSibling()
// -> Some<unknown> unknown any
// Предположим, что этот класс, как и `Some`, может наследоваться, и так до бесконечности ...
// Т.е. и здесь мы должны как-то определить тип по умолчанию и передать его в базовый класс.
class SomeExtended<TItem extends SomeExtended<TItem>> extends Some<TItem> {
_other: TItem
getOther(): TItem {
return this._other
}
}
const se = new SomeExtended()
se._item = se
se._other = se
// SomeExtended<SomeExtended<unknown>>
const e1 = se.getSelf().getSelf().getSelf()
// Оба ниже не работают.
const e2 = se.getSibling().getSibling().getSibling()
const e3 = se.getOther().getOther().getOther()
Другими словами:
- Класс умеет работать с типами, производными от самого класса(или с тем же интерфейсом).
- Пользовательская функция может "попросить" ссылку на элемент(в примере getSibling()), и она должна получить реальный тип.
Хотелось бы иметь конструкцию, подобную этой:
class _Some<TItem extends Some<TItem> = Some> { /* ... */ }
Ответы (1 шт):
Автор решения: Alexander Lonberg
→ Ссылка
Интересное наблюдение:
Если создать фиктивный(вспомогательный) тип, который хоть и является круговой ссылкой, но через посредника, ошибок уже не возникает.
Решение простое до безобразия.
// Просто создаем вспомогательный тип `_Some = Some`
type _Some = Some
class Some<TItem extends Some<TItem> = _Some> {
_item: TItem
getSibling(): TItem {
return this._item
}
getSelf(): this {
return this
}
}
const some = new Some()
some._item = some
const s2 = some.getSibling().getSibling().getSibling().getSibling()
// -> _Some _Some _Some _Some