Классы и интерфейсы в TypeScript

TypeScript, являясь надстройкой над JavaScript, значительно расширяет возможности работы с типами, что делает его мощным инструментом для разработки на платформе Angular. В этой главе рассмотрены ключевые особенности классов и интерфейсов в TypeScript, их взаимодействие, а также их роль в контексте Angular.

Классы в TypeScript

Класс — это шаблон для создания объектов с определенными свойствами и методами. TypeScript предоставляет синтаксис для объявления классов, который схож с тем, как это делается в других объектно-ориентированных языках программирования, таких как Java или C#. Однако TypeScript добавляет дополнительные возможности, такие как типизация свойств и методов.

Объявление класса

Для создания класса в TypeScript используется ключевое слово class. Основная структура класса включает конструктор, свойства и методы. Пример базового класса:

class Person {
  name: string;
  age: number;

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

  greet() {
    console.log(`Привет, меня зовут ${this.name}, мне ${this.age} лет.`);
  }
}

В этом примере класс Person имеет два свойства: name и age, а также метод greet, который выводит приветственное сообщение. Конструктор используется для инициализации свойств объекта.

Модификаторы доступа

В TypeScript классы поддерживают модификаторы доступа, которые управляют видимостью свойств и методов. Это позволяет контролировать, какие части класса доступны из других частей приложения.

  • public — по умолчанию все члены класса являются public, т.е. доступны извне.
  • private — члены класса, объявленные как private, не могут быть доступны за пределами класса.
  • protected — члены класса, объявленные как protected, могут быть доступны только в пределах класса и его наследников.

Пример использования модификаторов:

class Employee {
  public name: string;
  private salary: number;

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

  public displaySalary() {
    console.log(`Зарплата: ${this.salary}`);
  }
}
Наследование

TypeScript поддерживает наследование, что позволяет создавать классы, которые расширяют функциональность других классов. Для этого используется ключевое слово extends.

class Manager extends Employee {
  private department: string;

  constructor(name: string, salary: number, department: string) {
    super(name, salary); // вызов конструктора родительского класса
    this.department = department;
  }

  public displayDepartment() {
    console.log(`Отдел: ${this.department}`);
  }
}

В этом примере класс Manager наследует от класса Employee и добавляет дополнительное свойство department и метод displayDepartment.

Интерфейсы и их использование

Интерфейсы в TypeScript позволяют описывать структуру объектов, обеспечивая строгую типизацию. Интерфейсы можно использовать для того, чтобы описать требования к классам, функциям и объектам.

Объявление интерфейса

Интерфейс описывает форму объекта или класса. В отличие от классов, интерфейсы не могут содержать реализации методов. Они только описывают их сигнатуру.

interface PersonInterface {
  name: string;
  age: number;
  greet(): void;
}

Интерфейс PersonInterface описывает объект, который должен иметь два свойства (name и age) и метод greet.

Реализация интерфейса

Для того чтобы класс реализовывал интерфейс, он должен соответствовать всем свойствам и методам, которые описаны в интерфейсе. Важно отметить, что класс должен реализовывать все обязательные элементы интерфейса.

class Person implements PersonInterface {
  name: string;
  age: number;

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

  greet() {
    console.log(`Привет, меня зовут ${this.name}, мне ${this.age} лет.`);
  }
}

В данном примере класс Person реализует интерфейс PersonInterface. Все свойства и методы интерфейса реализованы в классе.

Интерфейсы для функций

Интерфейсы также могут быть использованы для описания типов функций. Например, интерфейс может описывать сигнатуру функции, включая типы ее параметров и возвращаемое значение.

interface GreetFunction {
  (name: string, age: number): void;
}

const greet: GreetFunction = (name, age) => {
  console.log(`Привет, меня зовут ${name}, мне ${age} лет.`);
};

Этот интерфейс описывает функцию greet, которая принимает два параметра — name и age — и не возвращает значения.

Классы и интерфейсы в контексте Angular

Angular активно использует классы и интерфейсы для создания компонентов, сервисов, директив и других сущностей. Классы в Angular являются основными строительными блоками приложения, и интерфейсы используются для строгой типизации данных и работы с API.

Пример компонента Angular с интерфейсом
import { Component } from '@angular/core';

interface User {
  name: string;
  email: string;
}

@Component({
  selector: 'app-user',
  template: `<h1>{{ user.name }}</h1><p>{{ user.email }}</p>`
})
export class UserComponent {
  user: User = { name: 'Иван', email: 'ivan@example.com' };
}

В этом примере компонент UserComponent использует интерфейс User, чтобы типизировать данные пользователя.

Пример сервиса в Angular с интерфейсом
import { Injectable } from '@angular/core';

interface ApiResponse {
  data: any;
  error?: string;
}

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  getData(): ApiResponse {
    // здесь может быть логика для получения данных
    return { data: { id: 1, name: 'Пример' } };
  }
}

Сервис ApiService использует интерфейс ApiResponse, чтобы типизировать ответ от API.

Заключение

Классы и интерфейсы являются неотъемлемой частью TypeScript и широко используются в Angular для структурирования приложения. Классы обеспечивают объектно-ориентированную модель, позволяя создавать компоненты, сервисы и другие элементы с четко определенной структурой. Интерфейсы, в свою очередь, обеспечивают строгую типизацию данных, улучшая читаемость кода и снижая вероятность ошибок на этапе компиляции.