#typescript #generics #dry #typescript-generics
Вопрос:
Почему в машинописном тексте невозможно выполнить следующее?
abstract class Generic<T> {
// ...
}
class Specific1 extends Generic<string> {
// ...
}
class Specific2 extends Generic<number> {
// ...
}
// this is where stuff goes wrong, compiler wants me to provide generic type arguments
// |
// ˅
abstract class Wrapper<T extends Generic> {
// ...
}
class Wrapper1 extends Wrapper<Specific1> {
// ...
}
class Wrapper2 extends Wrapper<Specific2> {
// ...
}
С Wrapper
помощью строки универсального класса я пытаюсь выразить, что я хочу , чтобы классы входили только в Wrapper
качестве универсального типа , который «специально реализован» Generic
, т. Е. Specific1
и Specific2
, в данном случае.
В проекте, над которым я работаю, у меня больше общих типов Generic
, чем показано здесь, а также больше реализаций, т. Е. Больше SpecificX
классов. Я мог бы избежать этой проблемы, передав все общие типы тем, к WrapperX
которым я переходил SpecificX
раньше, вот так:
class Specific1 extends Generic<type1, type2, type3> {
...
}
...
class Wrapper1 extends Wrapper<type1, type2, type3> {
...
}
… но я просто чувствую себя очень грязным, и мне интересно, есть ли лучший способ решить эту проблему. Я уже определил свой SpecificX
класс и его универсальные типы и хочу избежать повторения этого в другом месте.
Просто СУХО, но я не могу понять, как это сделать в машинописном виде 🙁
Ответ №1:
Если Wrapper
вы должны быть в состоянии обернуть что-либо Generic
, и вас на самом деле не волнует, каким Specific
может быть фактический тип, то явным образом пометьте параметр типа, как unknown
это будет сделано. С помощью следующего вы можете создавать обертки для всего, что расширяется Generic
.
abstract class Wrapper<T extends Generic<unknown>>
Если Wrapper
следует обернуть только один из Specific
типов, то вы можете подойти к проблеме с типом объединения. Возможно, было бы неплохо создать новый тип, содержащий все параметры. Это, безусловно, более подробно, но предотвращает обертывание чего-либо произвольного (например Generic<ButNotASpecificType>
).
class Specific1 extends Generic<string> {
// ...
}
class Specific2 extends Generic<number> {
// ...
}
type Specific = Specific1 | Specific2
abstract class Wrapper<T extends Specific>
Вот ссылка на игровую площадку для машинописи, демонстрирующая два подхода.
Комментарии:
1. Чувак, ты только что спас мне день.
unknown
оказалось именно то, что мне было нужно. У меня действительно есть некоторые ограничения, но я уже смоделировал их с помощью интерфейса. Спасибо!!!