Rasmus Olsson

Increasing TypeScript Type-Safety

June 30, 2021

Even though TypeScript have type-checking and type-safety you can opt out by using the type "any" for a variable or function. This "any" type have both upsides and downsides as described in the TypeScript documentation. It can for example give value when migrating from JavaScript to typescript and you want to do this gradually.

The any type is a powerful way to work with existing JavaScript, allowing you to gradually opt-in and opt-out of type checking during compilation.

But it can also get abused. TypeScript types can get very complex and it can be an easy escape route to just provide type "any" and move on with your code. Another example is third-party libraries that doesn't come with type definitions. Here you can write your own type definitions by proving a *.d.ts file but its also another easy escape route by using it as type "any".

Quoting from the TypeScript documentation:

After all, remember that all the convenience of any comes at the cost of losing type safety. Type safety is one of the main motivations for using TypeScript and you should try to avoid using any when not necessary.

So how do we as software developers make sure that we don't fall into the pit hole of overrepresented our code with type "any".

There are some common ways we can get rid of the type "any" completely. We can enable the ts compiler option: noImplicitAny together with an eslint rule no-explicit-any.

But how about the scenario where you can't just activate it because its just to much effort right now?

Let's say the team agreed on disallowing type "any" in the future and by using boy scouting eventually will get there or is currently migrating to TypeScript from JavaScript. How do we measure the progress towards removing it completely?

One tool that help is type-coverage.

A CLI tool to check type coverage for typescript code

We can install it to our dev dependencies and expose it to our scripts in package.json.

npm install --save-dev type-coverage "scripts": { ... "ts-coverage": "type-coverage" ... },

Perform npm run ts-coverage will give us the total coverage for example: 539 / 557 96.76%

To make sure we are not reducing our type-coverage we can add the --at-least argument.

"scripts": { ... "ts-coverage": "type-coverage -at-least 99" ... },

Now we can just add this as CI step and we can block the build from continue.

Another great tool is the typescript-coverage-report. It will give us a more details in a form of table and show us files missing coverage.

In example:

typescript-coverage-report

It includes the ts-coverage module so no need to install both.

"scripts": { ... "ts-coverage": "type-coverage-report --threshold 100" ... },

Thats it! Now we can measure our progress removing the type "any" and make sure we progress in the right direction.

References:

Happy Coding!

please share