You don't need TypeScript

TypeScript is a programming language that alike many other languages (CoffeeScript, Dart, PureScript et.al.) can compile to JavaScript.
TypeScript claims to be an extension to JavaScript - which adds static typing.

JavaScript is what programmers call "strongly typed". It means that the language has very strict typing rules, meaning you will not have issues like buffer overflow, like in the programming languages C and C++
JavaScript being strongly typed makes it more safe, and it has very good reasons to be safe, because JavaScript can be executed in web browsers. And as you are probably reading this blog post in a web browser, odds are that JavaScript is running on your machine right now! And you are probably not that worried - that the currently running code will escape it's environment and install a virus on your computer or steal your company secrets.
If you are worried about the JavaScript type system, you should also disable JavaScript in your browser. just saying ☺. (I recommend using a browser extension that makes JavaScript disabled by default, and that you only activate it on websites you trust)

While JavaScript is strongly typed, it's also dynamically typed.
Compared to statically typed, being dynamic means that JavaScript will convert from one type to another.
If you for example have a non decimal number JavaScript might store that as an integer, but if you have a decimal number, JavaScript will store it as a Float.
In JavaScript you never have to think about if you want an Integer, or a Float. JavaScript will automatically choose the best suitable type. And it does not matter if you compile to JavaScript from TypeScript, CoffeeScript or any other language that compiles to JavaScript. Once the JavaScript is executed by the engine, for example the browser's JavaScript engine, the JavaScript type system will do what it wants.
Some compile-to-JavaScript language compilers have some tricks that will influence the JavaScript type system, for example using the bitwise shift operator to make JavaScript use an Integer. eg. foo = int x compiles to foo = x|0.
TypeScript however does very little to make sure JavaScript use the correct types during runtime.
The value of TypeScript is that it can check the code for type errors when it compiles TypeScript to JavaScript. it does however not guarantee that after IO, eg. when reading data from a file, network, or user input, that the value will be a certain type. You can however guarantee that using plain vanilla JavaScript! Example:

In the code above, the JavaScript engine will automatically convert age to a number, then check if it's below 18, and then convert the result to a Boolean.
Only problem is if age is not a number, JavaScript will make it type NaN (not a number) and any operation on NaN will be false. eg. NaN>18?false NaN<18?false. So if this is a concern, that the user must enter a number, you will have to add a check for that:

Some TypeScript advocates will call this a "poor mans type checker". But TypeScript will however not help you here, you still have to explicitly check for NaN.

A sound type System can help you, but TypeScript is not

Here's a JavaScript to TypeScript example:

To make the function type safe, your would probably write it in TypeScript like this:

Only problem is that when the code above is executed, the head function will happily return a value that is not of type number!

When given an empty array, it will return undefined!

Instead of the TypeScript type system helping you find the error, you have to discover it yourself, and then manually add additional type annotations to help the type checker. It might look something like this:

You would have to add a lot of complicated code just to please the type checker. What a waste of time. You could instead do this in plain JavaScript:

How to find errors

In order to find errors in the code, you can study it hard, or manually test all possible states.
Some TypeScript advocates say you do not need to test your code if you write it in TypeScript...

Development usually goes something like this:

  1. You write code
  2. You manually test the code
  3. You upload the code to the production environment.
  4. Users start using the program, and finds errors.
  5. You fix the errors and upload the new code.
  6. Repeat step 4-5

The more users you have the more issues they will find, and hopefully they get fixed. Developers call this "battle hardening".

A sixth step can however be added to make it more efficient: When you fix the error, you also write code that automatically checks for that error. That way you can be sure that the same bug do not come back to hunt you.

When making changes to a program, there is a chance you will introduce new problems.
This is why making changes can be very scary, especially if you are new to the code-base, or if the code is hard to understand.
Errors often occurs because of edge cases you did not think about earlier when designing the code, and fixing it might require some ugly "hacks". When these fixes accumulate, the code will probably get harder and harder to understand.

So when you update the code, also write code that automatically checks if your code still works!
That way, the next time you update the code, you do not have to worry about breaking earlier fixes.

"battle hardening" is very effecient! If you release the code to 1000 users they will discover more bugs in one week -then you would discover in 10 years!
But you should not trust your users to report issues to you, only one in one thousands users will report errors, so when you get a bug report, is usually mean you have a "hidden iceberg" of users that have been hit by the bug and either worked around it or gave up. Instead you should make it so errors are detectable, and automatically reported.


Written by December 4th, 2019.


Follow me via RSS:   RSS https://zäta.com/rss_en.xml (copy to feed-reader)
or Github:   Github https://github.com/Z3TA