TypeScript: Exploring New Features and Their Advantages
Tags: typescript, javascript, discuss, learning
Published: 2023-07-04 04:32:37

Introduction:
TypeScript has gained significant popularity among developers due to its ability to enhance JavaScript with static typing, providing better tooling and improved developer experience. With each new release, TypeScript introduces new features and improvements that make it an even more powerful and versatile language. In this blog, we will delve into some of the latest features in TypeScript and discuss the advantages they bring to the development process.


## Nullish Coalescing (??) and Optional Chaining (?.):

One of the most awaited features in TypeScript was the introduction of the nullish coalescing operator (??) and optional chaining operator (?.). These operators help to simplify code by providing a concise way to handle null or undefined values. The nullish coalescing operator allows you to specify a default value when encountering null or undefined, while the optional chaining operator allows you to access properties and methods on objects without worrying about potential null or undefined errors. These features significantly reduce the need for explicit null checks and make code more robust and readable.

```
// Nullish Coalescing
const defaultValue = 'Default Value';
const userInput = null;

const result = userInput ?? defaultValue;
console.log(result); // Output: 'Default Value'

// Optional Chaining
const user = {
  name: 'Cristain',
  address: {
    city: 'New York',
  },
};

const cityName = user?.address?.city;
console.log(cityName); // Output: 'New York'

```
In the above code snippet, we demonstrate the usage of nullish coalescing and optional chaining. The nullish coalescing operator allows us to assign a default value (defaultValue) if the userInput is null or undefined. This prevents unexpected errors due to null values. The optional chaining operator allows us to safely access nested properties (city) without worrying about null or undefined values.


## Type Assertion Functions:

TypeScript 2.7 introduced a new feature called "type assertion functions" or "user-defined type guards." These functions allow you to define custom type guards that can narrow down the type of a variable within a specific code block. This feature enables developers to write more expressive and concise code when working with complex type hierarchies. By leveraging type assertion functions, you can eliminate unnecessary type assertions and ensure type safety throughout your codebase.

```
// Type Assertion Function
function isNumber(value: unknown): value is number {
  return typeof value === 'number';
}

function multiplyByTwo(value: unknown): number {
  if (isNumber(value)) {
    return value * 2;
  }
  throw new Error('Invalid input');
}

console.log(multiplyByTwo(5)); // Output: 10

```

In the above code snippet, we define the isNumber function as a type assertion function that checks if the value is of type number. The multiplyByTwo function uses the type assertion function to ensure that the input value is a number before performing the multiplication operation. This eliminates the need for additional type assertions or manual type checks and provides type safety during runtime.


## Improved Control over Class Property Declarations:

In TypeScript 2.8, the language introduced several enhancements related to class property declarations. The "readonly" modifier allows you to mark class properties as read-only, preventing accidental modifications. Additionally, the "parameter properties" feature simplifies the declaration and initialization of properties in classes by allowing you to declare and initialize properties directly in the constructor parameters. These enhancements promote better encapsulation and help catch potential bugs at compile-time.

```
// Readonly Property
class Person {
  readonly name: string;

  constructor(name: string) {
    this.name = name;
  }
}

const person = new Person('John');
person.name = 'Jane'; // Error: Cannot assign to 'name' because it is a read-only property

// Parameter Property
class Car {
  constructor(private readonly make: string, private readonly model: string) {}

  getFullModel(): string {
    return `${this.make} ${this.model}`;
  }
}

const myCar = new Car('Tesla', 'Model 3');
console.log(myCar.getFullModel()); // Output: 'Tesla Model 3'

```

In the above code snippet, we create a Person class with a read-only name property. Once initialized in the constructor, the name property cannot be modified. This ensures data integrity and prevents accidental changes to critical properties. Additionally, in the Car class, we use parameter properties to declare and initialize the make and model properties directly in the constructor parameters. This simplifies the class definition and improves code readability.