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

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

TypeScript унаследовал возможности непрерывно развивающегося JavaScript. Но если в JavaScript типы не имеют значения, то разработчики TypeScript раздвинули границы JavaScript, реализовав систему типов и сделав программный код JavaScript более удобным для обслуживания и применения. Он поддерживает прежнюю и текущую функциональность JavaScript, а также рассчитан на дальнейшие изменения. Разработчики могут подготовить простой и ясный программный код, в котором задействованы возможности ECMAScript 3 и более новых версий и реализованы отраслевые стандарты и рекомендуемые методы программирования. Если вам необходимо строить мощные, масштабируемые и удобные для обслуживания гибридные или веб-приложения, работающие с любым браузером, основным приложением или операционной системой, то TypeScript будет оптимальным вариантом.

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

Базовые типы

Концепция типов заключается в классификации данных, в том числе чисел, логических и строковых значений, символов или пользовательских данных, таких как класс или интерфейс. Это типичная конструкция объектно-ориентированных языков, таких как C#, C++ и Java. Благодаря типам повышается качество и удобство чтения программного кода, так как расширяется контекст внутри кода. Компилятору гораздо проще обнаруживать ошибки, если указаны типы.

TypeScript предоставляет необязательную (и очень богатую) систему типов для JavaScript. Типы существуют в JavaScript, но, составляя программный код, вы не можете контролировать, как они используются. JavaScript автоматически определяет тип на основе значения, присвоенного переменной. Попробуем разобраться в этой концепции на очень простом примере кода JavaScript (см. листинг 1).

Когда в приведенном примере присваивается значение «iPhone», браузер автоматически определяет тип данных переменной как строку. В следующей строке, когда мы назначаем число той же переменной, тип становится числом. Если вы захотите протестировать этот программный код, откройте браузер, скопируйте и вставьте приведенный в листинге код в окно Console («Консоль») и нажмите кнопку Enter («Ввод»), чтобы увидеть результат.

С другой стороны, в TypeScript вы указываете тип переменной; компилятор не позволит присвоить число строковой переменной (листинг 2).

Использование TypeScript с JavaScript предоставляет преимущества динамического языка, одновременно снижая количество ошибок, которые легко допустить в таком языке, поскольку ошибки обнаруживаются на этапе компиляции, когда их проще исправить, а не во время выполнения. Это особенно важно при работе над крупным проектом коллективом в 50 или 60 программистов. В этом случае вряд ли удастся привлечь только квалифицированных разработчиков пользовательского интерфейса. Среди них будут и другие специалисты (по серверному программному обеспечению, API и т. д.), и все они будут проектировать собственный код. Работая с TypeScript, не нужно беспокоиться о том, что делает каждый член команды, так как любые ошибки обнаруживаются во время компиляции. Это очень удобная возможность.

Теперь рассмотрим каждый тип TypeScript подробно.

Логический

Логический тип данных содержит значение true или false. Ниже показано, как объявить логическую переменную в TypeScript.

let isProductAvailable: boolean = true;

Численный

В отличие от различных объектно-ориентированных языков, таких как Java, C# и C++, которые предоставляют различные типы данных, например int, float и decimal, для хранения числового значения, TypeScript имеет только один числовой тип данных, именуемый number. Переменная с типом данных number может содержать любой численный литерал с плавающими, шестнадцатеричными и двоичными или восьмеричными значениями. В примере, приведенном в листинге 3, показаны числовые переменные, содержащие различные значения.

Строковый

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

let product: string = "iPhone";

Мы можем пойти дальше и посмотреть, насколько хорош новый синтаксис ECMAScript 6, используемый в TypeScript. Предполагая, что задано значение переменной продукта, вы можете объединить ее с другой строковой переменной с помощью обратной одиночной кавычки и знака ${}, что свойственно ECMAScript 6. Например, как примере, приведенном в листинге 4.

Массив

Тип данных array служит контейнером, который содержит любое число значений одного типа. В TypeScript существует два способа создания массива: один со знаком [], другой со встроенным универсальным классом array. Второй синтаксис лучше известен опытным разработчикам, использующим объектно-ориентированные языки, такие как C# или Java.

Ниже приводится пример с использованием знака []:

let products: string[] = ["iPhone 7",
   "iPhone 8", "iPhone X"];

А вот пример с использованием встроенного класса array:

let products: Array = ["iPhone 7",
   "iPhone 8", "iPhone X"];

Кортеж

В TypeScript имеется тип, именуемый кортежем, который полезен для обработки массивов с элементами из смешанных данных (например, [1, 4, ‘hello’, 38]). Если вы явно укажете массив чисел, как в приведенном выше примере, произойдет ошибка при компиляции кода. Но если используется кортеж, очень похожий на концепцию в объектно-ориентированных языках, то можно создать список строк и чисел или данных любых типов. Ниже показано, как создается кортеж в TypeScript:

let productInfo: [string, number] =
   ["iPhone X", 7500];

Кортеж достаточно интеллектуален, чтобы понять, какой тип объявлен в каждой позиции массива. В приведенном выше примере можно получить подстроку из строкового значения следующим образом: console. log(productInfo[0]. substr(0, 2));

Однако console. log(productInfo[1]. substr(3);0, 2)); выдаст ошибку, как показано на экране 1. Кортеж обнаружит, что вы используете число, а численный тип не имеет метода substring.

Использование кортежа
Экран 1. Использование кортежа

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

Обратите внимание, что нельзя присвоить значение типа, не указанное в объявлении кортежа. Например, productInfo[1] = true выдает ошибку во время компиляции, поскольку второй объявленный вами тип — числовой.

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

Перечислимый тип

Перечислимый тип нравится всем, и он применяется в TypeScript, как и в объектно-ориентированных языках, например C#. Вы можете вручную ввести значения, но если начать с 0, то это обеспечит единообразие с другими разработчиками в команде.

enum ProductCategories {MobilePhones = 1,
   Laptops, Desktops, Tablets,
   OtherAccessories};

Ниже приведен пример получения значения перечислимого элемента.

let category: ProductCategories =
   ProductCategories. MobilePhones;
// Выдается значение 1

Если вы хотите получить строковое значение enum, это можно сделать с помощью следующего программного кода.

let categoryName: string =
   ProductCategories[4]; // This will output
   “Tablets”

Обратите внимание, что число 4 представляет действительное значение enum. В приведенном выше случае число 4 представляет перечислимый элемент Tablets, так как он содержит это значение.

Произвольный тип

До этого момента мы перечисляли типы. Но возможны случаи, когда вы извлекаете данные из стороннего API и ничего не знаете о типе данных, возвращаемых из этого API. В таких случаях очень полезен произвольный тип данных, any.

let products: any = _apiService. GetProducts();
// The GetProducts() function is going
   to return some type of data from the API.

В приведенном ниже примере показано, как создать переменную произвольного типа и присвоить ей любое значение.

let product: any = "iPhone";
product = 200;
product = false;
product. HasValue();

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

Пустой тип

Тип данных void обычно используется в качестве возвращаемого типа при объявлении функций. Однако, если вы хотите назначить тип данных void переменной, она сможет содержать только два значения: undefined или null.

Ниже приводится пример функции с возвращаемым типом void.

function setProductName(name: string): void {
name = name;
}

Пример переменной, объявленной, как void, показан в листинге 5.

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

Неопределенный и нулевой типы

Как и JavaScript, TypeScript имеет типы undefined и null, которые также можно использовать как тип при объявлении переменной. Но объявление переменной типа undefined или null бессмысленно. Если создать переменную типа undefined, то обычно она ничего не означает и вам не удастся задействовать эту переменную для каких-либо целей.

let undefItem: undefined;
let nullItem: null;

Эти типы следует использовать как значение для переменной. В JavaScript null — значение назначения и имеет объектный тип. Оно может быть присвоено переменной как представление отсутствия значения. Undefined, с другой стороны, означает, что переменная объявлена, но ей еще не присвоено значение. Согласно рекомендациям по TypeScript, всегда следует выбирать undefined вместо null при присвоении объекту значения по умолчанию.

Определение типа

Определение типа — процесс вывода или задания типа данных для переменной на основе значения, присвоенного при объявлении. Если переменной не назначен тип во время объявления, компилятор TypeScript автоматически опред еляет тип на основе присвоенного значения. В листинге 6 приводится простой пример определения типа.

На экране 2 показано, как приведенный в листинге 6 программный код выглядит в редакторе кода.

Код листинга 6 в редакторе кода
Экран 2. Код листинга 6 в редакторе кода

В следующих статьях мы познакомимся с такими интересными возможностями TypeScript, как ECMAScript 6 и TypeScript.

Листинг 1. Пример кода JavaScript 
var product = "iPhone";
console.log(typeof (product));   // This code will output “string”
product = 100;
console.log(typeof (product));   // This code will output “number”
Листинг 2. Пример кода на TypeScript
let product: string = "iPhone";
console.log(typeof (product));   // This code will output “string”
product = 100;        // This code will emit an error at compilation
Листинг 3. Числовые переменные
let productPrice: number = 1500;
let productHexId: number = 0xf00d;
let productBinaryId: number = 0b1010;
let productOctalId: number = 0o744;
Листинг 4. Объединение строковых переменных
let message: string = `I love ${product}`;
console.log(message);          // Выводится "I love iPhone".
Листинг 5. Пример переменной типа void
let someItem: void; // Объявление переменной типа void.
someItem = undefined; // Задание undefined -- отсутствие ошибки компиляции
someItem = null; // Задание null -- отсутствие ошибки компиляции
someItem = ""; // Задание строкового значения приводит к ошибке компиляции
Листинг 6. Пример определения типа
let myProduct = "iPhone";
// Обратите внимание, что тип данных для переменной myProduct не объявлен
myProduct = 100;
// Приводит к ошибке, так как TS уже определил тип как строковый.