Type-Safe Reducers using TypeScript - Part 1 - Understanding Type Safety

Type-Safety is one of the super powers of statically typed programming languages like C#/Java. But for the ones who tries to accomplish anything and everything with these languages finds this also a curse. But a proper use of type-safety could enhance and ease the programming and provides complete end to end development experience.
But what about a language like JavaScript that is dynamic in nature. How do we ensure type-safety?
Oh, wait! Does JavaScript support data types? Oh come on, you shouldn't be surprised by this. If you do so, I suggest you stop reading here and head to Mozilla Developer Network site and read about JavaScript and supported data types a bit.
Let's get into our business here. According to Wikipedia
Type safety is the extent to which a programming language discourages or prevents type errors
To make sure we have understood this correctly, Let's quickly see an example,
In the method below we are attempting to find a string starts with a given value. The code looks a lot easier.
How could one make this to cause errors?
function startsWith(sourceString, findWhat){
return sourceString.indexOf(findWhat) === 0;
}
Well, we the humans as developers can! Let's see the various possibilities,
var someString = "Some value";
someString = undefined;
startsWith(someString, 'Some');
And the result is,

You might say that We should check if "someString" is undefined. Yes, that would solve this problem, would it solve all?
var someString = 6;
startsWith(someString, 'Some');
Here the variable "someString" doesn't contain a string value, it is a Number. Does number has a method named "indexOf". Don't think so!

Nothing that tells you here, hey "startsWith" method accepts only a valid string and it can't be undefined or null.
What if something that tells me this (You know what I mean is TypeScript) and makes me more productive by enabling me to write more stable code faster that breaks less at runtime.
With TypeScript one could harness the power of JavaScript's dynamic nature at runtime and sophisticated type system of TypeScript at compile time. This enables us to write code that is easy to understand and maintain.
The same method If I write using TypeScript, it would look like below,
function startsWith(sourceString: string, findWhat: string){
return sourceString.indexOf(findWhat) === 0;
}
And my intelligent IDE (Visual Studio Code) would warn me that I can't assign undefined to a string variable,

And if I tried to pass number,

There is nothing extra that we have written here except the type annotations.
But you must be aware that if this method is part of a JavaScript library and it is invoked by external code where our "startsWith" method is sent a value which is not a string, still the above discussed runtime errors would arise.
This is because "Type checking" is only done at the compile time.
We could avoid them by writing a defensive code and with unit test cases the same can be tested. That's a different world of topics all together. So, let's save it for some other day.
Then this question may arise, is it worth spending time in writing code in TypeScript?
Well, in my opinion it is definitely worth only if you are making use of type annotations properly. If you annotate your variables and function parameters with "any" more often than necessary then it is either you are not using TypeScript to its potential or may be not an option for your specific use case.
I think by now we are sure of the basic problem. Now let's see this problem through a different window called "redux".
If you are not sure of what Redux is, stop right here and go here.
While you are learning, I would have completed writing the Part 2 and updated the link here.
