Typescript is a superset of Javascript. It’s Javascript with type definitions and the code will be checked when compiling.
Why adopt TS if …
Javascript is fast to prototype
We can code fast with Javascript. The language is simple and allows us to do a lot of things. A prototyping time can be amazingly short. A downside of this is code readability. If we need to prototype something quickly to understand if the idea is viable, we skip thinking about architecture, writing documentation, tests. Eventually, we have a working piece. It has some bugs, but they can be fixed relatively fast. The piece is doing its intended job, we add more functionality to it, but some problems start to emerge.
To add a simple functionality, it’s hard to understand whether some service passes you an object with 20 fields, a string, or it may not pass anything at all. It’s difficult to fathom API contracts between code pieces you wrote! By writing more console.log’s you see the contracts and adjust the code to new requirements.
After some time, your colleague asks a team’s help to assist in debugging “what these objects are”. Next month a manager asks why it takes so long to modify a tiny bit of the functionality. The company even hired 5 additional developers for the last week. In the next week, the CEO along with CTO decided to rewrite the product from scratch.
Could the situation be different if the team adopted Typescript? Not really. But TS could help to eliminate bugs initially and with the next releases. Plus, it would take less time to modify existing code. Why? Doesn’t TS add more time to write, because you should think about types, write them down? We’ll get back to this question.
It eliminates problems when you write the code
IDEs have great TS support, so they will highlight potential errors you encounter. But, what kind of errors? Imagine you construct an object, convert it to some other form, pass it to a chain of 5 functions and then send the result to UI. It’s easy to follow the object properties when constructing it in the beginning. It’s difficult to follow a contract further. The next function can remove necessary fields from the object, another one will add some new ones, etc. With Typescript, you code how the object should look like, what properties are required, what are optional, and this contract will be followed. Otherwise, you’ll get compile errors(and errors highlights before that).
Another situation: there is a function that should be returning a number, but returns undefined. The function is complicated and we can’t exactly know where the problem occurs(i.e. why it can’t handle 10).
import {calculateXfromNum} from './otherService';
// there is a function from other service
// it calculates some number from other number
// this function should return number, at least we expect that
// judging by the code
const num = calculateXfromNum(10); // num is undefined
// this function expect a number
doStuffWithResult(num); // error
It improves code readability
Have you struggled with situations where you didn’t know what to expect from functions, 3rd-party services responses? Like in the example above. Types allow you to see what other functions take as arguments and what they’ll return. Have you seen the console.log debugging process? To understand what form an object has, people log it to the output a few times along the function execution.
You could use debugger also, it may help more. But why make things so complicated? Isn’t it enjoyable to know what this class method returns from the first glance at the code?
The subsequent question you may derive from the reasons above may be:
What about the time we spend on documenting types and writing more code? The coding won’t be so fast then.
It accelerates the development process
How is that possible?
If you think you will document all the types when using TS, thus it slows you down, that’s not the case. Typescript is smart enough to infer types from code. In cases where it can’t do that, you need to indicate a type explicitly. For example:
const n = 10; // n is number
// here, "num" can't be inferred, because you can pass anything here
// TS can't know that
function fn(num) {
return num + 10;
}
// if you point that "num" is number, TS knows the returning type
// will be a number too
function fn2(num: number) {
return num + 10;
}
Still, even if Typescript can infer types in simple cases, a developer should write complex types, so how the development becomes faster?
How much time do you think developers in mid/large-size JS projects spend on debugging to understand what an object will be returned by some function? I think a lot. We don’t write code for machines, but humans. The code should be understandable. You take a glance and you get a basic idea of what’s going on.
Learning Typescript syntax takes a few minutes to start coding if you already understand Javascript. What you need to know is how to declare type/interface. Then, you need some time to get used to advanced cases.
The additional development time will go to defining types, which isn’t so time-consuming. At least, it takes much less time than:
- asking a colleague where to find documentation about a service;
- asking a colleague who wrote that;
- asking the person who wrote that to explain what the form of an object is;
- writing comments about object type after debugging it;
- rewriting the comments because you didn’t expect other use cases;
Save yourself and your team many human hours of reading and understanding the code.
How to adopt
I’ll provide points for you to decide is it worth adopting at all, and how simple the process is.
It’s easy to learn
Understand how to declare types/interfaces and you’re good to go. Basically, it’s:
type Human = {
name: string;
age?: number;
}
const me: Human = {name: "Sergiy"};
While you write more code, you’ll get to know many other things along the way.
It’s easy to start right away
If you have a Javascript project already, all it takes for you to start writing TS code is to have Typescript installed, maybe some tsconfig configuration, and to set the –allowJs flag, so you can mix TS with JS code. As you code more, you’ll add more types, and maybe you convert all the codebase to TS. At least, you can TSify crucial parts of the code right now.
However, you’ll need to compile the project to Javascript. An additional build step in your workflow.
If you’re convinced to switch or migrate to Typescript, there are some thoughts to ponder about. As a person who leads a team, you should be responsible to explain to the developers why do you choose TS, what are pros and cons. Otherwise, programmers may think of it as a tool that slows them down. You may encounter situations when a developer writes something like that:
function parse(payload: any, options: object): any {
// ...
}
While it’s a valid code, it doesn’t add more readability. A developer may find using any is a good thing to save time. The idea the developers should understand is that if something is unknown, it’s better to figure out the actual type and document it.
Almost the same situation with wide types like object: the data may be an object with any properties, a function, an array. The more narrow type, the better.
Conclusion
Use Typescript if you need better code readability, hence development speed up in the long run. It takes a little time to get started with TS if you know Javascript. You can integrate TS in your Javascript project without rewriting JS parts right away.
Typescript is a tool that should be regarded as such and not as a thing that solves abstract problems like “improving the code”.