DEV Community

Discussion on: Pitch me on TypeScript

Collapse
 
nikfp profile image
Nik F P

I can say from my experience, using Typescript from the beginning of a project has always saved me time in the end, and helped me catch little "gotchas" through the process.

I'll give one example to the many that people have already posted. I have an API that I built that uses the following stack: Postgres > Prisma > A service layer that I built > a Graphql layer > HTTP Server for incoming requests. By defining my prisma schema and using Prisma's generators, I got all my model types for free as well as all the operations I can do on those models - AND if there is something subtle, like querying for a single record that could possibly come back null, Typescript spits out a warning if I don't handle the null case, so it's coercing me into deeper runtime safety checks all the way through. Then, I used the Graphql Schema with Grapqhl-Code-Generator to spit out types for everything at the Graphql layer and public facing API. I can then use those types through the whole resolver chain to make sure I'm returning the correct data and all the resolvers are implemented that need to be implemented, before I ever have to run the app. Most of the edge cases are addressed by virtue of TS catching when things can be one of many types, possibly undefined, etc - and not letting me pass values along until these cases are handled. Through some creative use of generics and type flowing I was able to type check the whole stack, all the way up to the resolver root, complete with typescript warnings whenever I changed the graphql schema and re-ran the generator. Any errors spit out by TS would point me to exactly what I needed to address.

THEN it got even better. This was a small MVP project so I went for code first, tests later (which you don't do, right?) and I found that a lot of the cases I would have written unit tests for..... were already accounted for by the TS compiler! So not only did I save dev time, I saved test time and debug time and the mental overhead involved in all 3. Sure, I could have written the tests anyway, but lack of time and the feedback from TS made that a lower priority.

All in all, this proved the point that I suspected. The initial setup and working out the type flowing- and learning how to use Graphlq-Code-Generator while doing this one - was very easily offset by the dev speed I maintained at the back end of the project.

Some common complaints I've seen on TS:

  • Slow compilation times - I recommend not using the standard typescript compiler if this is an issue. Set the compiler option in your tsconfig.json of "noEmit": true, and just use TSC for type checking. Use something faster to transpile when you are ready. I like Vite for this. There are also ways to hook into the build steps to run a type check from TSC before the build and fail it if something doesn't jive, and your IDE can make suggestions during dev.
  • Noisy code - This is a fair point. There is a lot more going on in a TS file. I can offer this observation though: by working through the types in each file, you are forced to more deeply consider the code you are writing, and since there is more to each file, it is much more apparent when something is trying to do too much. Thus, greater modularity and separation of concerns is encouraged by default.
  • No types for data from REST api's, having to write your own, and your code breaking when the API changes - Your code would break when the API changed in vanilla JS anyway. I don't see this as an issue specific to TS. At best, some forward thinking companies assemble type libraries for their API's or use OpenAPI which you can then use to generate types, or have opted for Grapqhl which can be introspected and types can be generated. It can be done and it's not as painful as one might think.
  • Complicated setup - I'll grant that setting up typescript is more complicated than setting up a standard JS project, but not really by that much. At one point you didn't know what all the stuff in a package.json file did, but you probably learned it along the way. This is the same thing, and once you know it and poke around with configs a few times it gets much easier. Also, most frameworks (React, Svelte, Vue, etc.) have bootstrapping commands that allow you to bring in TS already set up when you start a project.
  • Sometimes difficult to understand error messaging - I actually totally agree with this one. I've learned a few tricks to unpack what TS is telling me sometimes, but when you get into nested generics and complex types the error messages can turn into dumpster fires fast. This area of the ecosystem needs work. A quick google search of "Typescript errors are hard to read" proves that the internet at large agrees.