A Lesson In My Own Advice
A while ago I gave myself a painful lesson in something similar to what I've often recommend to others when asked: make many simple components rather than few complicated ones. The reason I fell in the trap this time was that the components didn't actually seem complicated – what I didn't realize was that the types involved in the components would become so complicated.
But a simple-ish component that ends up needing a complicated type system becomes a complicated component. And since most of the team wasn't very used to much TypeScript type comlexity, this type of complexity was especially heavy.
The task was the creation of a survey editor that had to support two types of surveys (a newer type and an older type). I made the survey editor components support both new and old surveys, and this was simple... until a rabbit hole of type ambiguities revealed itself.
Looking back, I should have made them separate components that in a similar-but-not-identical fashion combined shared, low-level components for input, layout, and so on.
The result would have been two sets of nearly-identical components on the upper abstraction levels, but in all of them, the types would always be only the immediately obvious ones, so there would be no need to do stuff like disambiguate the child types of t: T
when T extends A | B
.
Hopefully this type of type complexity pithole will be visible to me from the beginning next time. At the very least I'll know to retreat to the safety of many dumb components sooner. And if I'm lucky, TypeScript's own type inference will have improved in this area the next time I encounter something similar.