Before we dwell into the high realms of TypeScript, we need to understand why we need it in the first place.
TypeScript is just an extra layer added to JavaScript. It adds the static type checker property to the language, which helps us differentiate the types of values being used inside a program. With this layer added, TypeScript also induces some rules, as some methods are specific to certain data types. For example, the string type has the method toUpperCase
, which converts the string into uppercase, but using this method with a number will throw an error. JavaScript does not provide these checks, as it doesn’t care about the type—it just wants to run the program, which can make a program buggy.
Just like many languages, TypeScript not only has primitive data types like string, number, and boolean but also includes arrays, functions, and objects. On top of that, additional features like union types and interfaces help us extend the capabilities of the data types.
Before going down that road, we need to learn how TypeScript identifies different data types, a concept known as type annotation.
let variable1: string = "Hello World";
let variable2: number = 3;
let variable3: boolean = true;
As we can see from the example, after the variable, we have mentioned the data type. We can also completely ignore the data type, as TypeScript is capable enough to infer the data type from the value provided (type inference).
let variable1 = "hello world";
console.log(typeof(variable1)); // Output will be string
To specify an array, we use syntax like:
let variable1: string[] = ['alex', 'venice', 'rome'];
You might ask why string[] and not only []. That is because arrays can be of different types like numbers ([1, 2, 3, 4]), and we use number or string to identify the type.
This data type is used whenever we don’t have a clue about what the data type should be. We should refrain from using any as much as possible.
let variable1: any = "hello";
To define an object, we simply list its properties and their types.
let object: {x: number; y: string} = {x: 3, y: 'hello'};
With properties, we can do many things, like keeping them read-only, optional, etc.
Suppose we have a similar object structure or union which we use many times in a program. Rather than writing it multiple times, we name it and use it as many times as needed. This is known as type aliases.
type Point = {x: number; y: string};
type Point2 = number;
let variable1: Point = {x: 3, y: 'Alex'};
Sometimes, we want a data type to be either of two types, such as number or string. For that, we have union types.
let variable1: number | string;
We can only use those methods that are applicable to both types. If we still need to implement different methods, we can narrow down the value.
function printId(id: number | string) {
if (typeof id === "string") {
// In this branch, id is of type 'string'
console.log(id.toUpperCase());
} else {
// Here, id is of type 'number'
console.log(id);
}
}
This is another way to name an object.
interface Point {
key: number;
value: string;
}
Sometimes, we have more information about the type of value we are using, and we don’t want the compiler to infer the type. Type assertion comes in handy in such cases.
let code: any = 123;
let employeeCode = <number>code;
console.log(typeof(employeeCode)); // Output: number
We can use angle brackets <> or the as keyword.
So far, to declare a value, we used let or var. If we assign values to variables declared with let or var, type inference helps us determine the type of those variables. What happens if we declare a variable with the const keyword? Since the value won’t change, the value itself is the type of the variable. This is called a literal type, where the value is itself the type of the variable.
let variable1: 'Hello' | 'Welcome' | 'Hola';
variable1 = 'Geller'; // Error
const variable2 = 'Ross';
variable2 = "Joe"; // Error, it can only have 'Ross' as a value
Functions involve two things: the arguments passed and the return type. Both can be any data type. The syntax to define a function with types is as follows:
function test(arg1: string, arg2: string): string {
return "Hello World";
}