At this point, I don't really stop and think about it. I've done it so much for so long that it's pretty much automatic. But the way I used to do it was to put together what I thought was a good party, then to just run through all the types and check to make sure that whatever I faced, I had at least one that was offensively strong and no more than two who were defensively weak.
This is actually pretty similar to what my program does actually.
It automatically generates a chart that shows you how 'rank' against a type, and that rank is calculated through counting how many attacks/pokemon you have that are strong/weak against that type, with the entire breakdown of the calculations shown as well. It will show you which types your party is strongest against and weakest against. And when put beside the '# of pokemon' column (which shows how many pokemon of that type exist in the game) it's easy to see where the holes are in a party and to (hopefully) provide enough info to fix.