TypeScript – why you should care
Introduction
Building big web applications written in JavaScript is not a simple thing. We don’t have types, interfaces, enums etc. These features could be really helpful to maintenance our complex applications. To solve this problem – we can use TypeScript.
As it is stated on TypeScript landing page TypeScript is JavaScript that scales. It is a typed superset of JavaScript that compiles to plain JavaScript. It means that each and every JavaScript code is a valid typescript code.
Author assumes that readers has basic knowledge of JavaScript. All examples from the article can be tested on Typescript Playground.
Types
We can type all variables, not only as primitive types (string, boolean, number) but also as types or even intefaces. It allows us to get all information about available methods or properties to specific type i.e. for “number” we see methods ‘toFixed’ or ‘toExponential’. If we try use method which is not available on its prototype – compile error will appear.
const num: number = 12;
const str: string = 'string';
str.toFixed(2); // Property 'toFixed' does not exist on type 'string'
Let’s imagine a situation: We use REST Api to consume data from the server. It would be nice to have see all properties available in this response in our IDE.
We can create type which includes all properties we got from the server.
type ApiResponse = {
name: string;
surname: string;
car: {
name: string;
doors: number;
}
};
fetch(’/api’)
.then((res: Response) => res.json())
.then((res: ApiResponse) => {
res.name; // ok
res.age; // Property 'age' does not exist on type 'ApiResponse'
})
Of course it requires updating a type as soon as api changes but if we use typescript both on frontend and backend side we can use the same type for typing response and there’s no need to have two separate types.
Interfaces
Interfaces are similar to types. But in this case we can also use them for implementing methods and properties from interface in classes.
interface InterfaceToImplement {
str: string;
doSth: () => Promise<any>
};
class MyClass implements InterfaceToImplement {
str: string = ’some string’;
doSth() {
return Promise.resolve();
}
}
String enums
Since 2.4 version of typescript we can use string enums. It can be helpful for unifying actions names, creating a colour map. We can use it as a type as well.
enum Color {
Gray = ’#95a5a6’,
Green = ’#2ecc71’,
Blue = ’#3498db’
}
const myColor: Color = Color.Green; // ok
const chosenColor: Color = ’#2ecc71’; // Type '"#2ecc71"' is not assignable to type 'Color'.
Async/Await
This constructions can be helpful when we’d like to use async functions and write in a more synchronous way. By default – it can be transpile to ES6. If we want transpile it to ES5 or even ES3 – we have to add Promise polyfill to tsconfig.json.
async function greetMe(name: string): Promise<string> {
const greeting = await Promise.resolve(`Hi ${name}`);
return greeting;
}
greetMe(’John’).then(greeting => console.log(greeting)); // Hi John
Keyof
This feature is in Typescript since 2.1 version. It allows to declare a set of values which another objects will made from.
interface UserConfiguration {
name: string;
age: number;
}
type UserConfigurationOption = keyof UserConfiguration;
function keyValue<T extends UserConfigurationOption>(key: T, value: UserConfiguration[T]) {
console.log(`Setting: ${key} to ${value}`);
}
keyValue('name', 'John');
keyValue('age', 25);
keyValue('age', true); // Argument of type 'true' is not assignable to parameter of type 'number'.
Summary
This is just a small overview a few features available in Typescript. I’ve showed you most useful features in Typescript which are not available in ES6.