Skip to main content

TypeScript is ... an abstraction

· 4 min read
Homa Wong (unional)

TypeScript 4.7 is just around the corner.

I feel like it is a good time for me to update this TypeScript guidelines with what I have learn over the years and how am I using it nowadays.

As you can see, I've reorganized the repository and added this GitHub page to make it easier to share the knowledge.

In these blog posts, I'm going to share the bits and tips that I learned every day. Eventually this information will be incorporated into the guidelines.

To kick things off, I'm going to talk about what TypeScript is in 2022?

No no, not about the history of TypeScript.

It's about how I look at TypeScript and how I use it.

It's about when I follow the rules and when I break them.

I know all the rules, and then I know how to break 'em

TypeScript is an abstraction

Programming language is an abstraction.

The abstraction I'm talking about is not the abstraction of defining an interface or class or inheritance.

It's about the code you wrote, the text you typed in the .ts or .tsx file.

It is an abstraction over the actual binary code executed by the JavaScript engine.

A good abstraction emphasizes the important but sometimes has a cost of skipping over some details.

For example, the digital zeros and ones are an abstraction over the analog electrical currents.

Most of the time, at least in the sense of modern computing, missing the details on the different levels of electrical currents is a good thing. And we as a programmer don't ever need to think about it.

But to the eye of hardware engineer, it is not something they can ignore because there are physical rules they have to follow, and there are actual consequences when putting two wires too close to each other.

The abstraction of programming language is the same. It is good for most cases, but at some point it will start to breakdown.

rust is a good example of this. Its ownership model guarantee memory-safety and thread-safety. But there are rare cases you need to break the rules thus there is a unsafe keyword for it.

For TypeScript, it is not designed to be a 100% sounded language. That means you will run into those "rare" cases a lot more often.

You can learn more about soundness here and here.

Conclusion

So what should you do? Embrace it.

The unsafe keyword in TypeScript is any. While you should avoid using any in most cases, it is often enough that your tool chain should not prevent or punish you from using it.

You might think,

"hey, I'm working in a team and I don't want my team members who are less familiar with TypeScript to abuse the usage of any."

Yes, that is a legit concern, and you can make your own judgement for your circumstances.

My personal experience is that the number of times I have to break the rules are common enough that making exceptions for the tools (e.g. adding // eslint ignore comments) clutter the code and make the code harder to read.

My approach is to rely on unit tests and code reviews to make sure the usage of any are in check.

Also, defining the correct type is not always easy and can take significant amount of time. If you are working under a schedule, you might not have time to do that.

Another point to make is that since TypeScript is constantly improving, if you build some complex types, it might work in one version and break in another version.

ASK ME HOW I KNOW IT.

Of course, I'm not saying allowing your code litters with any and call it a day. You should keep track on those usages and clean it up when you get a chance to.

Converting any back to a proper type improves efficiency. As that is why we use TypeScript.

And you may discover some bugs along the way.