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

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

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

Краткий обзор этого руководства:

  • Как объявить интерфейсы Typescript
  • Работа с интерфейсами: варианты использования
  • Расширение интерфейса
  • Следующие шаги для вашего обучения

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

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

Интерфейсы гарантируют, что все реализовано должным образом.

Интерфейсы могут быть описаны явно или неявно созданы компилятором, когда он считывает объекты в коде. Мы объявляем интерфейс, используя ключевое слово interface в файле .ts. В следующем примере показан пример синтаксиса:

interface Dimension {
    width: string;
    height: string;
}

Здесь мы определили интерфейс со свойствами width и height, которые являются строками. Теперь мы можем реализовать интерфейс:

interface Dimension {
    width: string;
    height: string;
}
let _imagedim: Dimension = {
    width: "200px",
    height: "300px"
};

Давайте посмотрим на другой пример. Здесь мы объявляем интерфейс с именем User с ключевым словом interface. Свойства и методы, из которых состоит интерфейс, добавляются в фигурные скобки в виде пар key:value, точно так же, как мы добавляем элементы в обычный объект JavaScript.

interface User {
  id: number;
  firstName: string;
  lastName: string;
  getFullName(): string;
}

Мы можем использовать наш недавно созданный интерфейс в коде, добавив аннотацию к соответствующим объектам. Например, вот как создать новый пользовательский объект с пользовательским интерфейсом:

const user: User = {
  id: 12,
  firstName: "Josh",
  lastName: "",
  getFullName: () => `${firstName} ${lastName}`
};

При этом наш компилятор знает, какими свойствами должен обладать пользовательский объект. Если свойство отсутствует или его значение не того типа, который указан в интерфейсе, компилятор выдаст ошибку.

Интерфейс реализации класса

Мы можем использовать интерфейс с классом, используя ключевое слово implements, например:

class NameofClass implements InterfaceName {
}

Давайте посмотрим на этот интерфейс, работающий с классом. Здесь у нас есть интерфейс со свойствами ширины и высоты, оба типа строки. Существует также метод getWidth() со строкой возвращаемого значения.

interface Size {
    width : string,
    height: string,
    getWidth(): string; 
}
class Shapes implements Size {
    width: string;
    height: string;
    constructor (width:string, height:string) {
        this.width = width;
        this.height = height;
    }
    getWidth() {
        return this.width;
    }
}

Работа с интерфейсами

Теперь, когда мы знаем, как объявлять интерфейсы, давайте посмотрим на них в действии для нескольких распространенных случаев использования.

Указание дополнительных свойств

В предыдущем примере кода все свойства в интерфейсе являются обязательными. Если мы создадим новый объект с этим интерфейсом и опустим свойство, компилятор TypeScript выдаст ошибку.

Однако в некоторых случаях мы ожидаем, что наши объекты будут иметь необязательные свойства. Мы можем добиться этого, поместив вопросительный знак (?) непосредственно перед аннотацией типа свойства при объявлении интерфейса:

interface Post {
  title: string;
  content: string;
  tags?: string[];
}

В этом конкретном сценарии мы сообщаем компилятору, что объекты Post могут быть без тегов.

Очень полезно описывать интерфейсы таким образом, особенно если вы хотите предотвратить использование свойств, не включенных в интерфейс.

const validPostObj: Post {
  title: 'Post title',
  content: 'Some content for our post',
};
const invalidPostObj: Post = {
  title: 'Invalid post',
  content: 'Hello',
  meta: 'post description', // this will throw an error
  /* Type '{ title: string; content: string; meta: string; }' is not assignable to type 'Post'.
    Object literal may only specify known properties, and 'meta' does not exist in type 'Post'.
  */
};

Указание свойств только для чтения

Также можно пометить свойство в интерфейсе как доступное только для чтения. Мы можем сделать это, добавив ключевое слово readonly перед ключом свойства:

interface FulfilledOrder {
  itemsInOrder: number;
  totalCost: number;
  readonly dateCreated: Date;
}

Свойство только для чтения можно изменить только при первом создании объекта. Это означает, что если вы попытаетесь переназначить его значение, компилятор выдаст ошибку.

const order: FulfilledOrder = {
 itemsInOrder: 1,
 totalCost: 199.99,
 dateCreated: new Date(),
};
order.dateCreated = new Date(2021, 10, 29);

Это поведение похоже на то, что происходит, когда вы пытаетесь переназначить значение переменной, объявленной с помощью ключевого слова const в JavaScript.

Типы функций и классов

Интерфейсы также можно использовать для описания типов функций и для проверки структуры классов JavaScript.

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

interface SumFunc {
  (a: number, b: number): number;
}
const add: SumFunc = (a, b) => {
  return a + b;
}

Примечание. Нам не нужно было указывать тип параметра при создании нашей функции.

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

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

interface CarInterface {
  model: string;
  year: string;
  getUnitsSold(): number;
}
class Car implements CarInterface {
  model: string;
  year: string;
  getUnitsSold() {
    // logic to return number of units sold
    return 100;
  }
  constructor(model: string, year: string) {
    this.model = model;
    this.year = year;
  }
}

Примечание. Наши интерфейсы описывают общедоступную часть класса, а не как общедоступную, так и частную стороны.

Общие интерфейсы

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

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

Эти параметры можно заменить типом или другим интерфейсом позже в вашем коде.

Мы можем создать универсальный интерфейс, передав параметры типа с помощью угловых скобок (<>) в наш интерфейс.

interface PaginatedResponse<T> {
 data: T[];
 nextPageUrl?: string;
 previousPageUrl?: string;
}
interface Post {
 title: string;
 content: string;
 tags?: string[];
}
function loadDataFromApi() {
 fetch('/some/api/endpoint')
   .then((response) => response.json())
   .then((data: PaginatedResponse<Post>) => console.log(data));
}

В приведенном выше примере создается интерфейс PaginatedResponse, который мы можем повторно использовать для ввода данных, возвращаемых из источника API. Это можно повторно использовать в вашем коде для разных ресурсов API с одинаковой базовой структурой.

Расширение интерфейса

Как и классы, интерфейс может расширять другой интерфейс. Это позволяет вам копировать элементы одного интерфейса в другой, делая их повторно используемыми. Это дает вам гораздо больше гибкости.

Интерфейс может расширять один интерфейс, несколько интерфейсов или класс, используя ключевое слово extends. Мы можем расширить несколько интерфейсов, если они разделены запятыми.

interface PetsInterface {
  name: string;  
}
interface DogInterface extends PetsInterface {
  breed: string;
}
interface CatInterface extends PetsInterface {
  breed: string;
}

Чтобы реализовать наши интерфейсы Dog и Cat, мы также реализуем интерфейс Pets.

interface PetsInterface {
  name: string;  
}
interface DogInterface extends PetsInterface {
  breed: string;
}
interface CatInterface extends PetsInterface {
  breed: string;
}
class Cat implements CatInterface {
  name: string = 'Garfield';
  breed: string = 'Tabby';
}
class Dog implements DogInterface {
  name: string = 'Rover';
  breed: string = 'Poodle';
}

Что изучать дальше

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

Некоторые из этих функций, которые вы должны изучить далее, включают:

  • Типы утилит
  • Типы объединения и пересечения
  • перечисления
  • Тип охранников
  • Псевдонимы типов

Чтобы изучить эти инструменты и усовершенствовать свои навыки работы с TypeScript, ознакомьтесь с курсом обучения Educative TypeScript для разработчиков интерфейсов. Этот путь позволит вам безболезненно перенести свой опыт работы с JavaScript на TypeScript. К концу вы будете знать, как использовать продвинутый TypeScript в профессиональных проектах.

Если вы новичок в TypeScript или хотите улучшить свои навыки, это ваш универсальный магазин Typescript.

Удачного обучения!

Продолжить чтение о TypeScript на сайте Educational

Начать обсуждение

Почему вы считаете TypeScript хорошим языком для изучения? Была ли эта статья полезна? Дайте нам знать в комментариях ниже!