That's a good instinct, which is probably why people do it in TypeScript.
But, IMO this is not how TypeScript works best. When you write a function, you should fully type the data that you need for that function. This type is semantically tied to the implementation of the function: by writing out that type, you are "certifying" that that is the type that the function needs.
If you then go and use that type in another function, you've lost that "certification" in both places. You now have a type which is the union of the data structure needed by both functions.
This has two negative results:
1) There is no longer any point in the code where you are actually describing the specific contract requested by either function. And,
2) If you want to change Function A, you now have to spend 30 minutes reasoning out whether the contract required by Function B is still compatible with their shared type.
Result 2) is what causes the "I write the code and then I spend 2 hours making the types happy" issue that I was responding to.
Some side notes:
- I can't claim that this is the right approach for all typed languages. But the TypeScript compiler specifically is very happy to exchange one type for another as long as they're compatible. It is designed to handle "duck typing" like this at its core.
- I want to emphasize that syntactically it makes no difference whether you reuse types. And certainly it saves you keystrokes. The problem with reusing a type is you're omitting crucial semantic information about which "slice" of that type is needed for a function.
- I will accept that sometimes it's worthwhile to Pick<> some properties off of an object. But even this is usually avoidable.