Why should you invest in TypeScript? Does it make sense?
Every company follows a mission and when the user encounter bugs, it’s in the way of that mission. Because JavaScript is a non-typed language we encounter many bugs in our front-end application.
A well-written unit test may prevent these bugs but there is more to the story. We don’t like to write unit tests, we simply do it because it’s a part of the job or just to increase code coverage.
TypeScript, on the other hand, can also help to prevent these bugs along with the many other features it brings for developers.
Benefits of TypeScript
Many of us already know what TypeScript is but let’s get a basic idea of how it helps with some elementary examples.
Suppose we have a simple sayHello
function with one parameter name
function sayHello(name) {
return `Hey ${name}.`;
}
If we call this function with a name it simply returns Hello <name>
sayHello("Ashok Vishwakarma"); // Hello Ashok Vishwakarma.
Let’s call the same function with a different type of input, for example, an array of strings.
sayHello(["Ashok", "Vishwakarma"]); // Hello Ashok,Vishwaakrma.
With an object with a name property
sayHello({name: "Ashok"}); // Hello [object Object].
You can see that JavaScript does not generate any error but returns unexpected values for a different type of input.
Let’s convert the same function into TypeScript and see how it looks
function sayHello(name: string): string {
return `Hello ${name}.`;
}
Most of the above function looks exactly the same as the one we have written in JavaScript but we have annotated the parameter name
and return type of the function with string
type.
And if we call the same function the way we have called the JavaScript function we get the same output
sayHello("Ashok Vishwakarma"); // Hello Ashok Vishwakarma.
Now let’s call it an array of string
sayHello(["Ashok", "Vishwakarma"]); // Error: Argument of type 'string[]' is not assignable to parameter of type 'string'.
With an object with a name property
sayHello({name: "Ashok"}); // Error: Argument of type '{ name: string; }' is not assignable to parameter of type 'string'.
When we pass a different type of parameter to the function sayHello
TypeScript generates an error right after you typed it, telling us that you trying to pass a different type of parameter where the function only accepts a string.
We can also create custom types for complex objects and structs
interface User {
firstName: string;
lastName: string;
} function sayHello(user: User): string {
return `Hello ${user.firstName} ${user.lastName}`;
}
In the above example, we have created a User
type that contains firstName
and lastName
properties which are used to annotate the user
parameter of the function sayHello
Those are examples to tell you how Strict Type Checking helps you write robust and error-prone code.
Fewer bugs in production
Let’s take another example to see how it helps even more towards reducing bugs in production
Take an example of ReduxForm and suppose you have a very simple shared input component used by many forms in your application.
{
...
render(){
const { onBlur } = this.props;
return (
<input onBlur={onBlur} />
)
}
... }
In the render
method, you simply pass the onBlur
prop which is required for validations to run properly.
One day someone from the team made some changes in the same shared component and added a handleOnBlur
method to some other stuff
{ ... handleOnBlur(event){
const { onBlur } = this.props;
onBlur();
// other stuff
} render(){
return (
<input onBlur={this.handleOnBlur.bind(this)} />
)
} ... }
It looks like everything should work as it was working before, but there is an error.
{ ... handleOnBlur(event){
const { onBlur } = this.props;
onBlur(); // Event not passed
// other stuff
}
render(){
return (
<input onBlur={this.handleOnBlur.bind(this)} />
)
} ... }
And because of this little mistake, the form validation does not work and disables the form which users cannot submit.
So in the same example how TypeScript would have helped?
So if you go and check the type definitions for ReaduxForm, it clearly mentioned that onBlur
props require an argument type FocusEvent
in order to run the validations properly.
export interface CommonFieldProps extends CommonFieldInputProps {
onBlur: EventWithDataHandler<FocusEvent<any>>;
onChange: EventWithDataHandler<ChangeEvent<any>>;
}
So if you were using TypeScript, it would have thrown an error as soon as you typed that empty onBlur
method in your handleOnBlur
method.
{...handleOnBlur(event){
const { onBlur } = this.props;
onBlur(); // Expect 1 argument but got 0
// other stuff
}
render(){
return (
<input onBlur={this.handleOnBlur.bind(this)} />
)
}...}
And we would have passed the event parameter and thing would have worked the way it was working earlier.
These types of changes in our code as a developer have to do on a daily basis, and because, most of the time we are not aware that, what other parts of the application are using it, we end up breaking things and fixing them again and again.
TypeScript helps in these scenarios and prevents these mistakes by telling us the problems upfront.
To Type or Not to Type
There is a study done on a Million+ Github Repos and found that there are 15% of bugs can be prevented just by migrating them to TypeScript, read the details below
Other benefits of TypeScript
Other than types TypeScript adds more benefits for existing developers and testers along with the new hires.
Editor integration
TypeScript does not come with a compiler that will tell you when something has gone wrong, it has a language server that the editor can hook into for things like auto-completion, finding uses, refactoring, and more.
Code readability
Understanding someone else’s code is always hard, in front-end engineering most of the time we encounter code written by someone else, which we must understand in order to make changes to it.
TypeScript significantly improves the code readability with its inbuilt type support understanding code becomes way easier to understand what each and every object contains, what each and every method return, and what each and every variable holds.
Let’s compare the same with two examples one in JavaScript and other in TypeScript
// JavaScript
function getValue(data, key){
return data[key];
}
In the above JavaScript example of getValue
function, we don’t know what data contains or whether will it return the value or undefined.
But if we convert the same function into TypeScript
// TypeScript interface
User {
name: string;
email: string;
age: number;
} function getValue(data: User, key: string): string | number {
return data[key];
}
We clearly know what data contains and what type of value the function will return.
TypeScript, in my opinion, is the best thing happens to the JavaScript ecosystem so far. The tools like FlowJs from Facebook and etc are already there to enable strict type checking in JavaScript, but the TypeScript community is far bigger than anyone of them. Which helps to make our lives easier every day.
You can enable types for any public library using DefinetlyTyped, a community-maintained repo for more than 5000+ NPM packages.
There are other alternatives to TypeScript, the languages which compile to JavaScript, for example, Svelte, Dart and etc but they are completely different programming languages and do not carry the JavaScript experience. In order to get started, you have to invest time learning them from scratch.
Thanks for your time and consideration, now I leave you with some further readings which you can go through if you wish to explore further.
References
- The banner image credits go to Ionic Team https://ionic.io/blog/how-to-use-typescript-in-react
- The Case Study — Type or not to Type is done by the University College of London and Microsoft https://earlbarr.com/publications/typestudy.pdf