Выведение типов и аннотации типов в TypeScript
Одной из отличительных особенностей TypeScript является то, что он — статически типизированный язык. Это означает, что при объявлении переменные должны быть отнесены к соответствующим типам данных, поскольку это проверяется во время компиляции. Это отличается от синтаксиса JavaScript, динамически типизированного языка, который позволяет свободно объявлять переменные без необходимости указывать тип данных — интерпретатор присваивает переменным их типы во время выполнения программы. Наиболее важной особенностью использования статически типизированных языков для разработчиков является проверка ошибок на этапе компиляции, что увеличивает скорость разработки, поскольку сразу видно, есть ли в коде несоответствие типов или вы пытаетесь вызвать несуществующую функцию. Это более эффективный метод по сравнению с динамически типизированными языками, которые выполняют проверку ошибок во время выполнения.
В TypeScript переменные должны быть привязаны к типам, чтобы избежать нежелательных результатов. В TypeScript существует два основных способа представления типов: выведение типов (Type Inference) и аннотации типов (Type Annotations). В этой статье вы узнаете об аннотациях типов и выведение типов, о том, как их использовать, и о том, как лучше всего их применять. Давайте погрузимся в тему.
Выведение типа/Type Inference
Одним из способов представления типов в TypeScript является выведение типов. В этом разделе вы узнаете, что такое выведение типов, как TypeScript выводит типы и как их использовать.
Что такое выведение типов
Иногда мы можем не назначать типы, и компилятор TypeScript делает это за нас с помощью Выведения типа/Type Inference. Это процесс, при котором TypeScript автоматически определяет типы переменных с помощью компилятора TypeScript. Рассмотрим приведённую ниже строку кода:
let x = "OpenReplay is an open-source session replay suite";
Хотя мы явно не определили нашу переменную как строку, компилятор TypeScript автоматически определяет переменную x
как строку. Чтобы подтвердить это, рассмотрим приведённую ниже строку кода:
var x = "OpenReplay is an open-source session replay suite";
var y = 17;
x = y; // Compile-time Error: Type 'number' is not assignable to type 'string'
В приведённом выше фрагменте кода мы определяем переменную x
, не присваивая тип (помните, что компилятор TypeScript делает это за нас, поэтому она воспринимается как строка). Мы также определяем переменную y и присваиваем ей число 17
без явной аннотации типа, указывающей, что это число. Почему? Потому что мы хотим, чтобы компилятор TypeScript сделал это за нас путём выведения.
Далее, чтобы подтвердить, что TypeScript воспринимает x
как строку, а y
как число, присваиваем переменную y
переменной x
. При компиляции вылетает ошибка Type 'number' is not assignable to type 'string'
. Это доказывает, что TypeScript автоматически определил переменную x
как строку, а переменную y
как число.
Как TypeScript выводит типы
Предположим, что мы не присваиваем нашим переменным типы; как TypeScript узнает, какой тип данных следует использовать? В тот момент, когда мы инициализируем переменные и значения, компилятор TypeScript сканирует синтаксис и автоматически определяет тип. Если значение заключено в кавычки, то оно определяется как string
; если значение является числовым, то оно обозначается как number
, если оно либо true
, либо false
, то оно определяется как boolean
, и т.д.
Если у нас есть массив с различными типами данных, то TypeScript определяет типы с помощью алгоритма Best Common Type Algorithm. Используя алгоритм наилучшего общего типа, компилятор TypeScript выбирает тип данных, который подходит для всех значений в массиве. Рассмотрим приведённый ниже блок кода:
let x = [5, 6, null]
Здесь x присваивается несколько значений; TypeScript просматривает все значения и выбирает наилучший общий тип, представляющий все значения в массиве. В приведённом фрагменте кода у нас есть два типа — тип number
и тип null
. Первые два значения, 5
и 6
, представлены с помощью типа number
, а null
— с помощью типа null
. Поэтому компилятор TypeScript представляет тип данных нашей переменной x
как let x: (number | null)[]
.
Практический пример выведения типов в TypeScript
Рассмотрим, что происходит за кулисами компилятора TypeScript, когда мы определяем переменные без присвоения им типов. Рассмотрим приведённый ниже блок кода:
// Числа
let rating = 5;
let age = 63;
// Строки
let blog = "OpenReplay";
let feature = "Host your session replay tool yourself with OpenReplay";
// Логические значения
let x = true;
let y = false;
// Объект строк
const company = { companyName: "OpenReplay", location: "San Francisco" };
В приведённом выше фрагменте кода я определил переменные, которые TypeScript должен автоматически представлять в виде чисел, строк, булевых символов и объектов. Вы можете выполнить код в своём редакторе; я использую онлайновый TypeScript Playground.
Когда он запущен, и я нажимаю на строку модуля .D.TS
, то получаю следующее:
declare let rating: number;
declare let age: number;
declare let blog: string;
declare let feature: string;
declare let x: boolean;
declare let y: boolean;
declare const company: {
companyName: string;
location: string;
};
И хотя мы и не присваивали типы, компилятор TypeScript сделал это за нас. Он распознает тип number
, тип string
и тип boolean
.
Аннотации типа в TypeScript
В этом разделе вы узнаете, что такое аннотация типов, как объявлять типы с помощью аннотаций типов, а также о типах данных в аннотациях типов.
Аннотация типа — это способ представления типов данных в TypeScript. Она соответствует синтаксису variableName:type
. В отличие от вывода типов, здесь необходимо явно присваивать переменным их типы. Это может показаться большой работой, но это используется для обеспечения строгой проверки типов. Кроме того, это экономит время, так как ошибка несоответствия типа, обычно возникающая во время выполнения программы, при использовании аннотаций типов возникает во время компиляции. Аннотирование типов является хорошей практикой кодирования среди разработчиков, поскольку оно экономит время за счёт раннего обнаружения ошибок и обеспечивает хорошую читаемость кода. Давайте посмотрим, как это работает. Рассмотрим приведённый ниже блок кода:
let x: string = "OpenReplay is an open-source session replay suite";
Мы видим, что в этом блоке кода мы указываем, что наша переменная x
является строкой. Если мы попытаемся присвоить x
переменной другого типа данных, то во время компиляции будет выдана ошибка.
Объявление типов с использованием аннотаций
В аннотации типа мы назначаем типы для каждой переменной, объявленной в нашей кодовой базе. Рассмотрим пример кода:
// Числа
let rating: number = 5;
let age: number = 63;
// Строки
let blog: string = "OpenReplay";
let feature: string = "Host your session replay tool yourself with OpenReplay";
// Логические значения
let x: boolean = true;
let y: boolean = false;
// Объект строк
const company: { companyName: string; location: string } = {
companyName: "OpenReplay",
location: "San Francisco",
};
Вместо того чтобы позволить компилятору TypeScript автоматически присваивать типы, мы делаем это сами. Это очень хорошая практика для обеспечения безопасности кода, поскольку вероятность несовпадения типов очень мала.
Типы данных в аннотациях типов
Помимо присвоения типов переменным с помощью примитивных типов данных в JavaScript, мы также можем присваивать типы функциям, объектным типам и объединениям типов.
Чтобы присвоить функции тип, мы добавляем тип данных в качестве параметра, который определяет тип параметров, принимаемых функцией.
function firstName(name: string) {
console.log("My name is " + name.toUpperCase());
}Чтобы присвоить типы объектам, мы указываем имена переменных перед передачей значений. В приведённом ниже фрагменте кода мы указываем, что
companyName
иlocation
будут строкой непосредственно перед передачей значений.const company: { companyName: string; location: string } = {
companyName: "OpenReplay",
location: "San Francisco",
};Чтобы присвоить типы объединению (комбинации типов), мы указываем типы данных, которые хотим использовать в функции, разделённые вертикальной полосой.
function blog(id: number | string) {
console.log("OpenReplay is rated " + "id" + "star");
}
// OK
blog(5);
// Error
blog(true);
Здесь мы указываем, что переменные могут быть числового или строкового типа. Аргумент blog(true)
выдаёт ошибку, поскольку является логическим типом, не представленным в объединении.
Лучшая практика — выведение типа (Type Inference) или аннотации типов (Type Annotations)
Выбор между выводом типов и аннотациями типов зависит от сферы применения проекта. Однако использование аннотаций типов при назначении типов переменным в TypeScript является очень хорошей практикой. Использование аннотаций типов лучше по следующим причинам:
- Ускоренное время разработки, так как ошибки обнаруживаются на этапе компиляции.
- С помощью аннотаций легче читать код. Это важно при работе в команде.
- При использовании аннотаций типов очень мала вероятность несовпадения типов.
Заключение
В этой статье вы узнали о выведении типа и аннотации типов в TypeScript, о том, как TypeScript выводит типы, как объявлять типы с помощью аннотации, о типах данных в аннотации типов, а также о лучших практиках для вашего следующего проекта на TypeScript. Повеселитесь от души!