TypeScript for Java/C# Programmers


In this tutorial, we will discuss TypeScript, a great option for programmers who have experience with static typing languages like C# and Java. We can benefit from TypeScript's type system, which offers improved code completion, earlier error detection, and clearer communication between different parts of our program. It's essential to remember that TypeScript is based on JavaScript, which has some fundamental differences from traditional OOP languages. By understanding these differences, we can avoid common mistakes that programmers transitioning from C#/Java to TypeScript might make.

Syntax

Users can use the following syntax to create variables using TypeScript −

let variableName: type = value;

In this syntax, the let keyword is used to declare a variable, followed by the variable name, a colon, and the variable's data type. Finally, the value of the variable is assigned using an equal sign.

Features of TypeScript

Here are some features of TypeScript that Java/C# programmers should know −

Getting Started With TypeScript and JavaScript

Having a good understanding of JavaScript before diving into TypeScript is recommended. This will help us to write better JavaScript code and avoid common mistakes that programmers transitioning from other languages might make. Additionally, it's worth noting that TypeScript uses the same runtime as JavaScript, so any resources on JavaScript can be applied to TypeScript programs as well.

Classes and Object-Oriented Programming in TypeScript

In TypeScript, classes are a way to group data and functions together into a reusable structure. However, unlike in C# and Java, classes are not mandatory to organize code in TypeScript, and free functions can also be used.

If we choose to use classes, TypeScript offers many features, such as interfaces, inheritance, and static methods. This makes it easier to write object-oriented code in TypeScript. However, it's important to understand that classes are just one tool in TypeScript's toolbox, and using them for some situations is okay.

Free Functions and Static Classes

In TypeScript, we don't need to use constructs like singletons or static classes which are commonly used in languages like C# and Java. Instead, we can use free functions (functions not associated with a class) and classes when they make sense for the problem we're trying to solve. This gives us more flexibility in organizing our code.

Nominal Reified Type Systems and Types as Sets

In some programming languages like C# and Java, every value or object has one exact type defined by a class or primitive type. This is called a "nominal reified type system," meaning that the types are present at runtime and related by their declarations.

In TypeScript, however, it's better to think of a type as a set of values that share something in common. Instead of being based on explicit declarations, types are based on their structures and relationships with other types. This is called a "type as set" approach.

Thinking of types as sets allows for more natural operations like combining or intersecting types, which is useful for situations where a value can belong to multiple types at once. TypeScript provides several mechanisms for working with types in a set-theoretic way, making it a powerful tool for writing flexible and expressive code.

Structural Typing and its Consequences in TypeScript

Structural typing in TypeScript allows for more flexibility and dynamic programming as objects and functions can be used interchangeably as long as they have the same structure. This can make code more reusable and easier to refactor.

However, it can also lead to unexpected behavior if the structure of an object or function changes without warning, causing errors or type mismatches. Therefore, it is important to keep the potential risks and benefits in mind when using structural typing and to pay careful attention to the structure of objects and functions.

Example 1

In this example, we have created two objects, a person and an employee, with different properties using object literal syntax. a person has name and age properties, while the employee has name, age, and job title properties.

Next, we defined a Person type using an object interface with name and age properties. Then, we defined a printPerson function that takes a parameter of type Person and logs a message to the console.

Finally, we called the printPerson function twice with the person and employee objects as arguments. Since both objects have name and age properties that match the Person type, they can be passed as arguments to the printPerson function without error.

Users can observe in the output that the printPerson function correctly logs the name and age of both the person and employee objects to the console.

let person = { name: "John", age: 30 };
let employee = { name: "Mary", age: 25, jobTitle: "Software Engineer" };

type Person = { name: string; age: number };

function printPerson(person: Person) {
   console.log(`${person.name} is ${person.age} years old.`);
}

printPerson(person); 
printPerson(employee);

On compiling, it will generate the following JavaScript code −

var person = { name: "John", age: 30 };
var employee = { name: "Mary", age: 25, jobTitle: "Software Engineer" };
function printPerson(person) {
   console.log("".concat(person.name, " is ").concat(person.age, " years old."));
}
printPerson(person);
printPerson(employee);

Output

The above code will produce the following output −

John is 30 years old.
Mary is 25 years old.

Example 2

In this example, we have created a generic class called Stack that can be used to implement a stack data structure in TypeScript. The class has a type parameter T, which represents the type of the elements that will be stored in the stack.

Next, we defined a few methods that can be used to manipulate the stack, such as push, pop, and isEmpty. The push method takes an argument of type T and adds it to the top of the stack. The pop method removes and returns the element at the top of the stack, while the isEmpty method checks if the stack is empty.

Finally, we created an instance of the Stack class with string as the type parameter and added a few elements to the stack using the push method. We then called the pop method to remove the elements from the stack and logged the output to the console.

Users can observe in the output that the pop method returns elements of type string, which is the type parameter that was passed to the Stack class.

class Stack<T> {
   private items: T[] = []; 
   push(item: T): void {
      this.items.push(item);
   } 
   pop(): T | undefined {
      return this.items.pop();
   } 
   isEmpty(): boolean {
      return this.items.length === 0;
   }
} 
const stringStack = new Stack<string>();
stringStack.push("Hello");
stringStack.push("World");
stringStack.push("!"); 
while (!stringStack.isEmpty()) {
   const item = stringStack.pop();
   console.log(item);
}

On compiling, it will generate the following JavaScript code −

var Stack = /** @class */ (function () {
   function Stack() {
      this.items = [];
   }
   Stack.prototype.push = function (item) {
      this.items.push(item);
   };
   Stack.prototype.pop = function () {
      return this.items.pop();
   };
   Stack.prototype.isEmpty = function () {
      return this.items.length === 0;
   };
   return Stack;
}());
var stringStack = new Stack();
stringStack.push("Hello");
stringStack.push("World");
stringStack.push("!");
while (!stringStack.isEmpty()) {
var item = stringStack.pop();
   console.log(item);
}

Output

The above code will produce the following output −

!
World
Hello

In conclusion, TypeScript is a powerful language that offers several features that Java/C# programmers can benefit from. By co-learning JavaScript and TypeScript, developers can write more efficient, scalable, and maintainable code.

Updated on: 21-Aug-2023

97 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements