Typescript for Beginners. Understanding the Fundamentals.

Welcome to Typescript for Beginners. Understanding the Fundamentals. In recent years, Typescript has gained popularity in the web development community due to its many advantages over JavaScript. Typescript is an open-source programming language that is a superset of JavaScript. It adds a type system and object-oriented features to JavaScript, making it a more robust and scalable language.

This blog post is aimed at beginners who are interested in learning Typescript. We will discuss the fundamentals of Typescript and how it differs from JavaScript. We will also explore the benefits of using Typescript and provide code examples to help you understand the concepts better.

TypeScript for Beginners. Understanding the fundamentals.
TypeScript for Beginners. Understanding the fundamentals.

Table of Contents

What is Typescript

Typescript is a programming language that was created by Microsoft as a superset of JavaScript. It was designed to address some of the shortcomings of JavaScript by adding new features and functionalities to make the language more scalable and easier to maintain.

One of the primary advantages of Typescript is that it adds a type system to JavaScript. This allows developers to catch errors early on in the development process, thereby reducing the likelihood of bugs and making code more reliable. With Typescript, developers can specify the types of variables, parameters, and function return values, which helps catch type-related errors during compilation.

Another advantage of Typescript is that it allows for better code organization and scalability. With the addition of classes, interfaces, and other object-oriented features, developers can write code that is easier to understand, test, and maintain. Typescript also supports features like generics and type inference that make code more flexible and reusable.

In addition to the above benefits, Typescript also provides excellent tooling support, including a robust set of development tools like Visual Studio Code, which can help developers write code more efficiently.

Typescript is all about data types, to refresh your memory on JavaScript data types check out this post

How to install Typescript

1. Open a command prompt or terminal window.

2. Type the following command to install Typescript:

npm install -g typescript

This will install Typescript globally on your computer.

3. Once the installation is complete, you can check the version of Typescript installed by typing the following command:

tsc -v

This will display the version of Typescript installed on your computer.

With Typescript installed, you can now begin writing code in Typescript. You can create a Typescript file with the .ts extension and use the Typescript compiler (tsc) to compile the file to JavaScript. Here’s an example:

Create a new file named app.ts and add the following code:

function greeter(person: string) {
    return "Hello, " + person;
}

let user = "Jane User";

console.log(greeter(user));

Open a command prompt or terminal window and navigate to the directory where the app.ts file is saved.

Type the following command to compile the app.ts file to JavaScript:

tsc app.ts

This will generate a new file named app.js that contains the compiled JavaScript code.

Finally, run the app.js file using Node.js:

node app.js

This will execute the JavaScript code and output the result to the console.

Congratulations! You have successfully installed Typescript and compiled a Typescript file to JavaScript. With Typescript, you can now write scalable, reliable, and maintainable code for your web development projects.

Basic Types

In Typescript, basic types are used to represent different types of values in a program. Typescript supports various basic types, including boolean, number, string, array, tuple, enum, any, and void.

1. Boolean

The boolean type represents a logical value that can be either true or false. Here’s an example of how to declare a boolean variable in Typescript:

let isDone: boolean = false;

2. Number

The number type represents numeric values. Here’s an example of how to declare a number variable in Typescript:

let decimal: number = 6;

3. String

The string type represents a sequence of characters. Here’s an example of how to declare a string variable in Typescript:

let color: string = "blue";

4. Array:

The array type represents a list of values of the same type. Here’s an example of how to declare an array variable in Typescript:

let list: number[] = [1, 2, 3];

5. Tuple:

The tuple type represents an array with a fixed number of elements, where each element can have a different type. Here’s an example of how to declare a tuple variable in Typescript:

let tuple: [string, number] = ["hello", 10];

6. Enum:

The enum type represents a set of named constants. Here’s an example of how to declare an enum in Typescript:

enum Color {Red, Green, Blue};
let c: Color = Color.Green;

7. Any:

The any type represents any type. Here’s an example of how to declare a variable with the any type in Typescript:

let notSure: any = 4;

8. Void:

The void type represents the absence of any type. Here’s an example of how to declare a variable with the void type in Typescript:

let voidValue: void = undefined;

Typescript supports various basic types, including boolean, number, string, array, tuple, enum, any, and void. These types allow developers to write more robust and maintainable code by providing a way to specify the type of values in a program. By using basic types, developers can catch type-related errors early on in the development process and write code that is easier to understand and maintain.

Functions

Functions are an essential part of programming, and Typescript supports various types of functions, including named functions, anonymous functions, arrow functions, and recursive functions.

1. Named Functions:

Named functions are functions that have a name and can be called using the name. Here’s an example of how to define a named function in Typescript:

function add(x: number, y: number): number {
  return x + y;
}

In the above example, we have defined a named function called add that takes two parameters of type number and returns a value of type number.

2. Anonymous Functions:

Anonymous functions are functions that do not have a name and are usually defined as function expressions. Here’s an example of how to define an anonymous function in Typescript:

let multiply = function(x: number, y: number): number {
  return x * y;
}

In the above example, we have defined an anonymous function called multiply that takes two parameters of type number and returns a value of type number. We have assigned this function to a variable called multiply.

3. Recursive Functions:

Recursive functions are functions that call themselves. Here’s an example of how to define a recursive function in Typescript:

function factorial(n: number): number {
  if (n == 0) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

In the above example, we have defined a recursive function called factorial that takes a parameter of type number and returns a value of type number. The function calculates the factorial of a given number by calling itself recursively.

Typescript also supports optional and default parameters, rest parameters, and function overloading, which allows you to define multiple functions with the same name but different parameter lists. Here’s an example of how to define a function with optional and default parameters:

function buildName(firstName: string, lastName?: string) {
  if (lastName)
    return firstName + " " + lastName;
  else
    return firstName;
}

let result1 = buildName("Bob");                  // works correctly now
let result2 = buildName("Bob", "Adams");         // works correctly now
let result3 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result4 = buildName("Bob", undefined);       // works correctly now

In summary, functions are a crucial part of programming, and Typescript supports various types of functions, including named functions, anonymous functions, arrow functions, and recursive functions. By using Typescript’s features like optional and default parameters, rest parameters, and function overloading, developers can write more flexible and maintainable code.

Interfaces

Interfaces are a fundamental concept in Typescript that allow developers to define contracts that objects must adhere to. They provide a way to define the shape of an object, including its properties and methods.

An interface is essentially a blueprint that describes the structure of an object. It specifies the names and types of properties that an object must have, as well as the types of methods that an object must implement.

Here’s an example of how to define an interface in Typescript:

interface Person {
  firstName: string;
  lastName: string;
  age: number;
}

function greet(person: Person) {
  return "Hello, " + person.firstName + " " + person.lastName;
}

let person = {
  firstName: "John",
  lastName: "Doe",
  age: 30
};

console.log(greet(person)); // Output: Hello, John Doe

In the above example, we have defined an interface called Person that has three properties: firstName of type string, lastName of type string, and age of type number. We have also defined a function called greet that takes a parameter of type Person and returns a greeting string.

We have then created an object that conforms to the Person interface and passed it as an argument to the greet function. The function uses the properties of the Person object to construct a greeting string.

Interfaces can also extend other interfaces, allowing you to define more complex object structures. Here’s an example of how to extend an interface in Typescript:

interface Person {
  firstName: string;
  lastName: string;
}

interface Employee extends Person {
  id: number;
}

function greet(employee: Employee) {
  return "Hello, " + employee.firstName + " " + employee.lastName;
}

let employee = {
  firstName: "John",
  lastName: "Doe",
  id: 1234
};

console.log(greet(employee)); // Output: Hello, John Doe

In the above example, we have defined an interface called Employee that extends the Person interface. The Employee interface has an additional property called id of type number.

We have then defined a function called greet that takes a parameter of type Employee and returns a greeting string. We have created an object that conforms to the Employee interface and passed it as an argument to the greet function.

Interfaces are an essential concept in Typescript that allow developers to define contracts that objects must adhere to. They provide a way to define the shape of an object, including its properties and methods. By using interfaces, developers can write more robust and maintainable code by ensuring that objects conform to a predefined structure.

Classes

Classes are an essential part of object-oriented programming, and Typescript supports class-based object-oriented programming. Classes in Typescript are similar to classes in other object-oriented programming languages like Java and C#.

A class is essentially a blueprint for creating objects that share common properties and behaviors. It defines a set of properties and methods that an object can have. Classes are used to create instances of objects that share the same behavior and structure.

Here’s an example of how to define a class in Typescript:

class Person {
  firstName: string;
  lastName: string;

  constructor(firstName: string, lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  greet() {
    return "Hello, " + this.firstName + " " + this.lastName;
  }
}

let person = new Person("John", "Doe");
console.log(person.greet()); // Output: Hello, John Doe

In the above example, we have defined a class called Person that has two properties: firstName and lastName, both of type string. We have also defined a constructor that takes two parameters of type string and sets the firstName and lastName properties of the object.

We have then defined a method called greet that returns a greeting string using the firstName and lastName properties of the object. Finally, we have created an instance of the Person class and called the greet method on the object.

Classes in Typescript also support inheritance, allowing you to define a hierarchy of classes. Here’s an example of how to define a derived class in Typescript:

class Employee extends Person {
  id: number;

  constructor(firstName: string, lastName: string, id: number) {
    super(firstName, lastName);
    this.id = id;
  }

  getInfo() {
    return this.id + " " + this.firstName + " " + this.lastName;
  }
}

let employee = new Employee("John", "Doe", 1234);
console.log(employee.getInfo()); // Output: 1234 John Doe

In the above example, we have defined a derived class called Employee that extends the Person class. The Employee class has an additional property called id of type number.

We have then defined a constructor that calls the super method to invoke the constructor of the Person class and sets the id property of the object. Finally, we have defined a method called getInfo that returns a string using the id, firstName, and lastName properties of the object.

Classes are an essential part of object-oriented programming, and Typescript supports class-based object-oriented programming. By using classes, developers can create objects that share common properties and behaviors and write more organized and maintainable code. With the support for inheritance, Typescript classes offer an effective way to create complex object hierarchies.

Generics

Generics in Typescript are a powerful feature that allows developers to create flexible and reusable code. Generics enable writing code that can work with a variety of data types, without losing the type safety provided by Typescript.

Generics work by allowing developers to define placeholders for types that are used in functions, classes, and interfaces. These placeholders are then replaced with actual types when the code is executed.

Here’s an example of how to define a generic function in Typescript:

function identity<T>(arg: T): T {
  return arg;
}

let output1 = identity<string>("hello");  // Output: hello
let output2 = identity<number>(10);       // Output: 10

In the above example, we have defined a function called identity that takes a parameter of type T and returns a value of type T. The <T> syntax defines the placeholder for the type, which is then replaced with the actual type when the function is called.

We have then called the identity function with two different data types: string and number. In both cases, the function returns a value of the same type that was passed as an argument.

Generics can also be used in classes and interfaces. Here’s an example of how to define a generic class in Typescript:

class Stack<T> {
  private items: T[] = [];

  push(item: T) {
    this.items.push(item);
  }

  pop(): T {
    return this.items.pop();
  }
}

let stack = new Stack<number>();
stack.push(1);
stack.push(2);
console.log(stack.pop());  // Output: 2
console.log(stack.pop());  // Output: 1

In the above example, we have defined a generic class called Stack that has a single placeholder for the data type of the items in the stack. The class has methods to push and pop items from the stack.

We have then created an instance of the Stack class with a data type of number and pushed two items onto the stack. We have then called the pop method twice to retrieve the items from the stack.

Generics in Typescript allow developers to write flexible and reusable code that can work with a variety of data types, without losing the type safety provided by Typescript. Generics can be used in functions, classes, and interfaces to create generic code that can be used with any data type. By using generics, developers can write more efficient and maintainable code that can handle different data types without duplicating code.

Enums

Enums in Typescript are a way to define a set of named constants that represent a fixed set of values. Enums allow developers to define a set of values that are related and give them a meaningful name.

In Typescript, enums are defined using the enum keyword. Here’s an example of how to define an enum in Typescript:

enum Color {
  Red,
  Green,
  Blue
}

let c: Color = Color.Green;
console.log(c); // Output: 1

In the above example, we have defined an enum called Color with three values: Red, Green, and Blue. The default underlying value for the first enum member is 0, and subsequent members are assigned the next numeric value by default.

We have then created a variable c of type Color and assigned it the value Color.Green. When we log the value of c, it outputs 1, which is the numeric value assigned to Green.

Enums can also have string values assigned to them. Here’s an example of how to define an enum with string values:

enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

let d: Direction = Direction.Up;
console.log(d); // Output: UP

In the above example, we have defined an enum called Direction with four string values: Up, Down, Left, and Right. Each member of the enum has a string value assigned to it.

We have then created a variable d of type Direction and assigned it the value Direction.Up. When we log the value of d, it outputs "UP", which is the string value assigned to Up.

Enums can also have computed values assigned to them. Here’s an example of how to define an enum with computed values:

enum LogLevel {
  Error = 1,
  Warn,
  Info,
  Debug
}

function printLogLevel(level: LogLevel) {
  console.log(level + ": " + LogLevel[level]);
}

printLogLevel(LogLevel.Warn); // Output: 2: Warn

In the above example, we have defined an enum called LogLevel with four values. The first value Error has an explicit value of 1, and subsequent values are assigned the next numeric value by default.

We have then defined a function called printLogLevel that takes a parameter of type LogLevel and logs the numeric value and the name of the enum member.

We have then called the printLogLevel function with the value LogLevel.Warn. The function logs the value 2: Warn, which is the numeric value assigned to Warn and the name of the enum member.

Enums in Typescript are a way to define a set of named constants that represent a fixed set of values. Enums allow developers to define a set of values that are related and give them a meaningful name. Enums can have numeric, string, or computed values assigned to them, providing flexibility and allowing developers to use them in different scenarios. By using enums, developers can write more expressive and maintainable code.

Type Inference

Type inference is a powerful feature in Typescript that allows the compiler to determine the data type of a variable or expression automatically. Type inference is based on the context in which the variable or expression is used.

In Typescript, type inference allows developers to write code with fewer explicit type annotations. The compiler can deduce the data types of variables and expressions from the code, making it easier to write and maintain code.

Here’s an example of how type inference works in Typescript:

let x = 10;
let y = "Hello, world!";
let z = true;

console.log(typeof x); // Output: number
console.log(typeof y); // Output: string
console.log(typeof z); // Output: boolean

In the above example, we have defined three variables: x, y, and z. We have assigned the value 10 to x, the string "Hello, world!" to y, and the boolean value true to z.

We have then used the typeof operator to log the data type of each variable. The Typescript compiler can deduce the data type of each variable based on the assigned value, and the output shows the correct data type of each variable.

Type inference also works with function return types. Here’s an example of how type inference works with function return types in Typescript:

function add(a: number, b: number) {
  return a + b;
}

let result = add(1, 2);
console.log(typeof result); // Output: number

In the above example, we have defined a function called add that takes two parameters of type number and returns their sum. We have then called the add function with two arguments of type number.

We have then assigned the result of the add function to a variable called result. The Typescript compiler can deduce the data type of the result variable from the return type of the add function, which is number.

Type inference can also work with more complex expressions. Here’s an example of how type inference works with more complex expressions:

let numbers = [1, 2, 3, 4, 5];
let filteredNumbers = numbers.filter(n => n % 2 == 0);

console.log(filteredNumbers); // Output: [2, 4]

In the above example, we have defined an array of numbers called numbers. We have then used the filter method to create a new array called filteredNumbers that contains only the even numbers from the numbers array.

We have not explicitly defined the data type of the filteredNumbers variable. However, the Typescript compiler can deduce the data type of the filteredNumbers variable from the return type of the filter method, which is an array of numbers.

Benefits of using Typescript

In summary, type inference is a powerful feature in Typescript that allows the compiler to determine the data type of a variable or expression automatically based on the context in which it is used. Type inference makes it easier to write and maintain code by reducing the need for explicit type annotations. By using type inference, developers can write code more efficiently and with fewer errors.

Typescript is a superset of JavaScript that adds optional static typing and other advanced features to the language. Typescript has become increasingly popular among web developers due to its benefits in terms of code quality, maintainability, and developer productivity.

Here are some of the key benefits of using Typescript:

  1. Type Safety: One of the main benefits of Typescript is the type safety it provides. Typescript enables developers to catch errors before runtime by detecting issues during compilation. This helps reduce the likelihood of bugs and increases the reliability of code.
  2. Code Maintainability: Typescript also enhances code maintainability by making it easier to read, refactor, and navigate code. With Typescript, developers can write self-documented code, as the types provide additional information on the data types and interfaces. This makes it easier for other developers to understand the codebase and collaborate more efficiently.
  3. Advanced Language Features: Typescript also provides advanced language features like enums, interfaces, classes, and generics. These features help developers write more expressive and maintainable code.
  4. Compatibility with Existing JavaScript Code: Typescript is fully compatible with existing JavaScript code, which makes it easy to migrate to Typescript without any major refactoring.
  5. Improved Developer Productivity: Typescript helps improve developer productivity by providing better tools and support for debugging, refactoring, and testing. This enables developers to work more efficiently and spend less time fixing bugs and more time writing new features.
  6. Large and Active Community: Typescript has a large and active community of developers and contributors. This community provides support, resources, and tools that make it easier to work with Typescript and address any issues that arise.

Typescript provides numerous benefits to web developers, including type safety, code maintainability, advanced language features, compatibility with existing JavaScript code, improved developer productivity, and a large and active community. By using Typescript, developers can write more reliable and maintainable code, collaborate more efficiently, and enhance their overall development experience.

Watch the video below for a brief overview of ‘Typescript for Beginners‘

Conclusion

Typescript is a valuable addition to the web development toolkit that can help developers produce better quality code more efficiently. By leveraging Typescript’s powerful features, developers can reduce the likelihood of errors and improve the reliability of their code. This ultimately translates into a better user experience, as bugs are less likely to occur and the application runs more smoothly.

One of the key benefits of Typescript is its advanced language features, such as interfaces, classes, and generics, which enable developers to write more expressive and maintainable code. These features make it easier to create complex applications that are more easily understood and modified over time.

Typescript’s compatibility with existing JavaScript code allows developers to leverage the vast ecosystem of JavaScript libraries and tools. This compatibility also makes it easy to integrate Typescript into existing codebases, which helps teams gradually adopt Typescript without the need for a complete rewrite.

Finally, Typescript’s large and active community ensures that developers have access to a wealth of resources and support, including tools, libraries, and documentation. This community makes it easier for developers to learn and adopt Typescript, while also providing a platform for collaboration and sharing of ideas.

For more information on Typescript check out these resources:
Typescript.org
w3schools.com
Github.com