Typescript generics: write modular, decoupled, and reusable code