TypeScript is a natural extension of JavaScript that’s used in many projects in place of JavaScript.
However, not everyone knows how it actually works.
In this article, we’ll look at how TypeScript makes JavaScript projects better.
Type Coercion
JavaScript does data type coercion of its variables when it does certain operations.
It produces consistent results, we just have to know how it works.
If we use the ==
operator to compare objects, then type coercion will be done before comparison operations are done.
For instance, we may have:
let applePrice = 1;
let orangePrice = '1';
if (applePrice == orangePrice) {
//...
}
Then both will be converted to numbers before comparison.
When we write:
let totalPrice = applePrice + orangePrice;
then both will be converted to strings before concatenation, which is probably not what we want.
Avoiding Unintentional Type Coercion
To make our lives easier, we should take steps to avoid unintentional data type coercion.
To do that, we can use the ===
operator for comparisons and convert types explicitly first before doing concatenation.
For instance, we can write:
let applePrice = 1;
let orangePrice = '1';
if (applePrice === orangePrice) {
//...
}
for comparison, and:
let totalPrice = Number(applePrice) + Number(orangePrice);
===
does comparison without applying data type coercion.
And we prevent concatenation with the +
sign by using the Number
function to convert both operands to numbers before adding them.
The Benefits of Explicit Type Coercion
We can use type coercion to our benefit.
For instance, we can use the ||
to coerce null
, undefined
or other falsy values to false
so that the ||
operator will return the 2nd operand.
For instance, if we have:
let firstName;
let secondName = firstName || "jane";
Since firstName
is undefined
, then ||
operator will coerce firstName
to false
and return the 2nd operand, which is 'jane'
.
Therefore, we can use the ||
operator to return a default value inc case the first is falsy.
Working with Functions
Functions are a building block of JavaScript.
We can define functions to run code that’s invoked repeatedly.
For instance, we can write:
const addPrices = (first, second) => {
return first + second;
};
Then we can call it by writing:
let applePrice = 1;
let orangePrice = 2;
const totalPrice = addPrices(applePrice, orangePrice);
The addPrices
function received number values when we call it above.
However, JavaScript doesn’t do any validation when we pass in the variables to the function.
Therefore, we may get unexpected results.
This is where TypeScript can help, we can validate the data types before the function is called when the arguments are passed in.
Function Results
In JavaScript, function return types are determined by the value we return.
It can be anything, depending on what we return.
For instance, if we have:
let applePrice = 1;
let orangePrice = 2;
const totalPrice = addPrices(applePrice, orangePrice);
then we return a number.
On the other hand, if we have:
let applePrice = 1;
let orangePrice = '2';
const totalPrice = addPrices(applePrice, orangePrice);
Then addPrices
returns a string.
This may be a problem since we probably don’t want to concatenate instead of add.
Only 2 numbers are added together. Otherwise, it’s concatenated.
Also, we don’t have to pass in all arguments.
For instance, if we add the 3rd argument to addPrices
as follows:
const addPrices = (first, second, third) => {
return first + second + third;
};
let applePrice = 1;
let orangePrice = 2;
const totalPrice = addPrices(applePrice, orangePrice);
Then we get NaN
because third
is undefined
, and adding number and undefined
results in NaN
.
Avoiding Argument Mismatch Problems
In JavaScript, we can set a default value for a parameter that we know are optional.
For instance, we can write:
const addPrices = (first, second, third = 0) => {
return first + second + third;
};
or, we can use the rest parameter notation to put some or all arguments into an array.
If third
has no value passed in, then third
is set to 0.
We can write:
const addPrices = (...rest) => {
return rest.reduce((a, b) => a + b, 0);
};
Then rest
is an array as the spread operator puts all the arguments into an array.
Conclusion
TypeScript just uses JavaScript’s type system.
It tames the dynamic nature of JavaScript’s type system by restricting the types of parameters and return types of functions.