At the end of the day, you've got reusable code (types) consumed at compile time (types don't exist at runtime) and you need them to be available to both clients and servers during their separate compilation processes.
It doesn't really matter how you distribute the code—zip file, copy-paste, carrier pigeon—but for ubiquity and standardization I think it makes sense to make them available in an npm
module. I don't know what you mean by a "better way"; this is just compile-time code sharing, the same way most of npm
is filled with libraries of code to be shared at compile time.
I wouldn't go out of my way to make a separate module just for types, but I would consider a separate module just for pieces shared between client and server. This prevents you from mixing server-only code into your clients, assuming the server is open-source JS/TS in the first place. If you need to add any reusable bits—say, model objects, data validators or JSON utilities—those would have a natural place to go. Of course, on day 1 this might be mostly useful for types, but if client and server share concerns with types I think it's natural that those concerns would grow over time.