История первая. Дженерики.
Короч, как вы знаете у TS есть условия на типах, которые выглядят как
type A<T> = T extends string ? T : number;
Этот механизм позволяет пилить довольно суровую наркоманию по типу той, которая находится на скриншоте. Однако эта штука не только суровая, забористая, так что её нормально не смогли спроектировать перед добавлением даже ребята из MS.
Мы имеем на проекте styled-components(SC), react-select(RS), react-hook-form(RHF) и собственную логику для стилизации этих селектов(далее L). И наш код выглядит как-то так:
RHF(L(SC(RS()))). Т.е. декораторы, которые декораторами погоняют, то бишь обычный код для дизайн системы.В итоге, так как RHF и RS имеют долбанутые дженерики в своей логике, то TS в какой-то момент превращает тип
type X<T> = T extends true ? string : number просто в string | number. Потому что походу вычисления достаточно сложные и, так как нет спеки, можно и захачить костыль, из-за чего весь код превращается в единую семантическую ошибку.Как это решать? Я пока выработал одно правило. Если ты пишешь декораторы, то под ними желательно не иметь дженериков в принципе. А если они нужны, то хотя бы избегать условий в них, чтобы в неожиданный момент эти условия не схлопнулись.
Для избегания условий можно поступать в стиле golang и писать что-то в стиле
type SingleSelect<OT> = ReactSelect<OT, false>;
type MultiSelect<OT> = ReactSelect<OT, true>;
Да, получается шумно, но оно хотя бы работает
