Advanced TypeScript: Generics, Interfaces, and Classes

If you’ve been using TypeScript for a while, you’re probably already familiar with basic features like types, interfaces, and classes. But did you know that TypeScript also offers more advanced features like generics, interfaces as function types, and abstract classes?

If you’re ready to take your skills to the next level, you’re in luck. In this article, we’ll dive into the world of advanced TypeScript and explore some of its most powerful features – generics, interfaces, and classes.

So, grab your favorite beverage, put on your learning hat, and let’s get started!

Generics

Generics are a way to make a function, class, or interface work with a variety of types. Instead of using a specific type in your code, you can use a placeholder that will be replaced with a specific type at runtime.

In TypeScript, generics are denoted by a type parameter wrapped in angle brackets. Here’s an example:

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

let output = identity("Hello, world!");  // "Hello, world!"

In this example, we’re using the type parameter T to denote a placeholder for any type. We’re then using that placeholder as the type for our argument and our return value.

This means that we can pass in any type we want, and TypeScript will infer the correct type:

let output = identity("Hello, world!");  // string
let output2 = identity(42);             // number

Notice that the function is returning exactly what was passed in, but with the type inferred from the input. This is very useful in cases where you want to return the same value as the input, but with a different type, for example when you want to convert a string to a number.

function toNumber<T extends string | number | boolean>(input: T): number | undefined {
  if (typeof input === "string") {
    return parseFloat(input);
  } else if (typeof input === "number") {
    return input;
  } else {
    return undefined;
  }
}

console.log(toNumber(42));          // 42
console.log(toNumber("42"));        // 42
console.log(toNumber(true));        // undefined
console.log(toNumber([1, 2, 3]));   // undefined

This function toNumber() is taking a generic type parameter T that extends string, number, or boolean. It returns either the parsed float of the input (parseFloat()) or undefined.

Interfaces

In TypeScript, interfaces define the shape of objects, which means they define what properties an object must have and what their types must be. But they also define function types, which enable you to define the signature of a function.

Here’s an example of an interface for an object that has a name and an age property:

interface Person {
  name: string;
  age: number;
}

We can then create an object that conforms to this interface:

let person: Person = { name: "Alice", age: 25 };

Interfaces can also define function types. Let’s define an interface for a function that takes two numbers and returns a number:

interface BinaryOperation {
  (a: number, b: number): number;
}

We can then use this interface to define a function:

let add: BinaryOperation = (a, b) => a + b;
let total = add(1, 2);  // 3

Interfaces are very useful for defining the API of a module or library, and for structuring your application’s data model.

Classes

Classes in TypeScript work the same way they do in other object-oriented programming languages, like Java or C#. They are a way to encapsulate data and behavior into a cohesive unit.

Here’s an example of a simple class in TypeScript:

class Greeter {
  private message: string;

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

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

let greeter = new Greeter("world");
console.log(greeter.greet());   // "Hello, world"

This class Greeter has a private property called message that is set when an instance is created, and a public method called greet() that returns a string. We’re then creating an instance of the class with the new keyword and calling the greet() method.

Classes can also inherit from each other, which enables you to reuse functionality from an existing class. Here’s an example:

class Animal {
  name: string;

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

  speak(): string {
    return "I am an animal";
  }
}

class Dog extends Animal {
  speak(): string {
    return "I am a dog named " + this.name;
  }
}

let dog = new Dog("Sparky");
console.log(dog.speak());   // "I am a dog named Sparky"

This class Dog extends the Animal class, which means it inherits all of its properties and methods. It also overrides the speak() method to return a different string.

Classes can also implement interfaces, which means they must conform to the interface’s shape. Here’s an example:

interface Serializable {
  toJSON(): string;
}

class Person implements Serializable {
  name: string;

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

  toJSON(): string {
    return JSON.stringify({ name: this.name });
  }
}

let person = new Person("Alice");
console.log(person.toJSON());   // "{"name":"Alice"}"

This class Person implements the Serializable interface, which means it must have a toJSON() method that returns a string. We’re then creating an instance of the class and calling the toJSON() method.

Classes are very useful for structuring your application’s business logic and for encapsulating data and behavior.

Conclusion

In this article, we’ve explored some of TypeScript’s most powerful features – generics, interfaces, and classes. We’ve learned how to use generics to create functions, classes, and interfaces that work with a variety of types. We’ve seen how interfaces define the shape of objects and function types, and we’ve used them to define the API of our modules and libraries. And finally, we’ve seen how classes enable us to encapsulate data and behavior into a cohesive unit, and how they can inherit from each other and implement interfaces.

If you’re just getting started with TypeScript, these features may seem a bit overwhelming at first. But with practice, you’ll start to see how you can use them to make your code more concise, readable, and maintainable. So, keep learning, keep coding, and keep having fun!

Editor Recommended Sites

AI and Tech News
Best Online AI Courses
Classic Writing Analysis
Tears of the Kingdom Roleplay
Developer Cheatsheets - Software Engineer Cheat sheet & Programming Cheatsheet: Developer Cheat sheets to learn any language, framework or cloud service
Learn Go: Learn programming in Go programming language by Google. A complete course. Tutorials on packages
Last Edu: Find online education online. Free university and college courses on machine learning, AI, computer science
Neo4j App: Neo4j tutorials for graph app deployment
CI/CD Videos - CICD Deep Dive Courses & CI CD Masterclass Video: Videos of continuous integration, continuous deployment