Inevitably, those candidates that layout their types, and think about the structure before they start coding come up with convoluted interfaces, leave unused class/struct/type member variables, duplicate data, or are simply unable to complete the problem because they've coded themselves into a rabbit hole.
The best candidates decide what the public interface will look like, create the method signatures that they need and then start coding the logic. They add parameters/member variables only when they discover they're needed.
In the end they arrive at a minimal and feature complete solution, rarely getting stuck on the way there. I've changed my own style of thinking about a problem as a result of this. Now I code outside-in, instead of inside-out.
If the most difficult part of the problem is the algorithm, then start with that and figure out the types along the way.
If the most difficult part are the types / data representation then start with that and worry about the algorithms later.
If both are difficult, then they need to be considered together and come up with a holistic solution. These are the kinds of problems that often take a two or more rewrites before you come up with something you're happy with.
I sometimes end up with a messy and crappy solution on my first try, but it does work (sort-of) and then I just start from scratch again, liberally copying stuff over but also deleting/changing a lot of stuff, as needed.
So in something like Haskell the types are strong enough that going with a types first approach makes a lot of sense. Often once you have the types laid out, many functions will only have a handful of sensible implementations that are even possible at all.
In something as primitive as C or Go (before generics) types don't tell you much at all. So laying them out first doesn't give you much at all. You might make a mental (or physical) note of what you are trying to achieve on what data, and then start coding.
In Haskell you could express a lot of the content of that note in the types; but in C and Go many or even most things are done via side-effects, and their type system doesn't track these at all.
I’d write a parser by first writing code to open a file (for example) to get a collection of tokens, then loop through them and decide what to do for each one. I’d use those decisions to guide my design of the output types.
Others, it seems, start by designing the output types up front and use that to guide the design of the program logic.
I’m the opposite to you - I tend to think logic-first. So, for example, when thinking about a parser I’d start by writing code to read tokens. I’ve struggled to follow tutorials that instead start by defining types to represent an AST.
Different approaches to problem-solving also lead to different preferences in terms of programming languages. In particular, I’m perfectly happy working in dynamically-typed languages for small-to-medium projects. Many programmers seem to be opposed to dynamic languages on principle - I believe that’s related to thinking types-first.