Что такое TypeScript — характеристики и методы работы

История TypeScript

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

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

Ориентирован TypeScript на прикладные задачи – он помогает кратко и точно выражать идеи (писать более читаемый код), а также обеспечивает масштабируемость и безопасность приложений. Эта надстройка вокруг основного языка JavaScript дает разработчикам статическую типизацию и приведение типов.

Характеристики TypeScript

TypeScript – это просто JavaScript. TypeScript начинается в JavaScript и заканчивается в JavaScript. Typescript принимает базовые структурные элементы программы от JavaScript. Соответственно, чтобы использовать TypeScript, нужно знать только JavaScript. С целью выполнения, код TypeScript полностью конвертируется в JavaScript эквивалент.

TypeScript поддерживает другие JS библиотеки. Компилируемый TypeScript может быть использован любым JavaScript кодом. JavaScript, сгенерированный с помощью TypeScript, может повторно использовать все существующие JavaScript фреймворки, инструменты и библиотеки.

JavaScript – это TypeScript. Это значит, что любой валидный .js файл можно переименовать в .ts и скомпилировать с другими TypeScript файлами.

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

Почему стоит попробовать TypeScript?

Размышляя о том, почему имеет смысл попробовать поработать на TypeScript, я выделил несколько основных пунктов:

  • Возможность жестко описать каждый элемент приложения — это, вероятно, исключает возможность неверной реализации или некорректного вызова методов; Заставляет разработчиков продумать логику (например, в методах) до самой реализации; Не дает возможность изменить один кусок приложения, сломав другой;
  • Возможность описать область видимости свойств класса — еще один барьер, который ограничивает разработчика от совершения ошибок;
  • Из-за жесткой архитектуры, возможно, необходимо писать меньше тестов — все параметры методов жестко описаны, и если код скомпилировался, тогда, вероятно, каждый вызов является валидным, и не требует дополнительной проверки;
  • Можно настроить проект таким образом, что любой некомпилируемый код (фактически, код с синтаксической ошибкой) нельзя будет закоммитить. Случаи в которых разработчик позволяет себе закоммитить сломанный код в обход проверок перед коммитом не рассматриваем;
  • Многие конструкции в TypeScript имеют жесткий формат, поэтому многие из ошибок форматирования кода (в соответствии каким-то принятым в коллективе нормам) исключены. Я думаю что это плюс, потому что процесс ревью кода часто выявляет ошибки форматирования, на которые тратится ценное время. Если это время можно потратить на другие более полезные активности — это уже плюс.

С другой стороны, есть ряд минусов:

  • Чтобы использовать какой-то внешний инструмент (читай «библиотеку» или «фреймворк»), тогда сигнатуру каждого из методов каждого модуля этого инструмента необходимо описать, чтобы компилятор не выбрасывал ошибки (он просто не будет знать про ваш инструмент). Если это популярный инструмент, тогда, вероятнее всего, описание интерфейсов можно найти в этом репозитории. Если нет — придется описывать самому;
  • Вероятно, самый большой минус (возможно, временный) — порог вхождения и количество специалистов на рынке. Сейчас почти нет специалистов которые знают этот язык. Это плохо, потому что любой солидный проект со временем переходит на этап поддержки, и в случае потери специалистов, найти им замену будет сложнее. Возможно, я ошибаюсь, но я пришел к этому выводу опираясь на статистику Github (ссылка) — создано лишь ~6k репозиториев с TypeScript кодом против ~1.4kk на JavaScript;
  • На разработку тратится больше времени, в сравнении с JavaScript. Это вызвано тем, что помимо реализации класса необходимо описать все задействованные интерфейсы, сигнатуры методов.

Как установить TypeScript

Чтобы использовать TypeScript, установите сначала Node.JS. Как это сделать, можете прочитать в нашей статье. После этого введите в консоли команду:

npm install -g typescript

Теперь создайте в папке со скриптами файл с расширением .ts — в нём мы будем писать код. Для компиляции кода пригодится команда tsc. Чтобы скомпилировать файл app.ts, введите команду:

tsc app.ts

Если всё пройдёт успешно, то в папке появится файл app.js, который и подключим к странице.

Также можно составить конфиг в файле tsconfig.json, чтобы максимально упростить компиляцию.

{ «compilerOptions»: { «target»: «es5», «removeComments»: true, «outFile»: «app.js» } }

В compilerOptions хранятся все параметры для компилятора:

  • target — стандарт JS, в который компилируется код. Здесь указан ECMAScript 5, потому что он поддерживается всеми современными браузерами;
  • removeComments — параметр определяет, нужно ли удалять комментарии;
  • outFile — файл, в который сохраняется JS-код.

Теперь достаточно просто вводить команду tsc без параметров, чтобы скомпилировать наш TypeScript. Обратите внимание, что компилятор затронет все файлы с расширением .ts в текущей директории.

Начинаем работать

Перехожу к небольшим заметкам, которые я оставлял в уме по мере работы с TypeScript.

Сборка

Прежде всего, было необходимо написать сборщик тестового проекта. Есть несколько NPM пакетов для gulp которые позволяют компилировать TypeScript код в JavaScript. Без знания что выбрать я начал пробовать все пакеты в том порядке, в каком мне их выдал Google. Оказалось, что не все пакеты используют последнюю версию компилятора (последняя версия была 1.5.0), и из-за этого код который компилировался на сайте TypeScript (ссылка) не компилировался плагином для gulp. Методом проб и ошибок я остановился на пакете gulp-tsc, который поддерживает все версии компилятора и работает «на ура».

Компиляция

Каждый интерфейс, сигнатура каждого экспортированного метода: все это должно быть известно компилятору, иначе он откажется компилировать код. Я работал с AMD модулями (об этом чуть позже), и при импорте одних модулей в другие возникала проблема — компилятор совершенно ничего не знал об существовании других модулей.
Для этих целей существуют .d.ts файлы — файлы, в которых нужно определить что конкретно экспортирует тот или иной модуль, какие глобальные переменные и функции определены.
На первый взгляд — все просто. На деле здесь обнаружился подводный камень (смотрим код ниже).
Создадим файл foo.ts в котором определим модуль foo:
/// export = { bar: () => ‘baz’ }
Создадим файл bar.ts в котором определим модуль bar, который импортирует модуль foo:
/// import foo = require(‘foo’); // Ошибка: «Cannot find external module ‘foo’.» export = { foo: foo }
Мы получили ошибку «Не удается найти внешний модуль foo.». Почему так происходит? Так происходит потому что этот модуль мы нигде не определили и компилятор про него не знает.
Создадим файл foo.d.ts, в котором расскажем компилятору, что есть такой модуль foo, и он экспортирует один метод bar:
declare module foo { export function bar(): string }
Мы добавили определение модуля и теперь все похоже на правду, все должно заработать, не правда ли? Неправда, потому что ровным счетом ничего от этого не изменилось — компилятор по-прежнему не может найти модуль foo. Вопрос — почему?
Решение оказалось неожиданным — название модуля было определено не в кавычках.
Работающий код файла foo.d.ts:
declare module ‘foo’ { export function bar(): string }
Едем дальше…

AMD

Конечно, если TypeScript дает возможность создавать AMD-модули и можно красиво импортировать зависимости, почему бы этим не воспользоваться хотя бы для теста?
Я попробовал — в TypeScript по-определению нельзя генерировать модули с именами. TypeScript дает возможность генерировать модули без имен, не более. Мне показалось, что это было бы странно, и оказалось, что это можно обойти.
Пример модуля, который будет скомпилирован в модуль с именем:
/// export = { bar: () => ‘baz’ }

Синтаксис TypeScript

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

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

var num: number =5;

Основные типы данных:

Ключевое слово Тип данных Описание Пример кода
Any Динамичный Описывает данные, тип которых может быть неизвестен на момент написания приложения. let AnyVar: any = «green»; console.log(AnyVar); // сейчас AnyVar – это string AnyVar = 30; console.log(AnyVar); // сейчас AnyVar – это number
Number Числовой Целые числа или числа с плавающей запятой let decimal: number = 6;
String Строчный Последовательность символов Unicode let color: string = «blue»; color = ‘grey’;
Boolean Логический Используется для логических значений true и false let isDone: boolean = false;
Void Void Отсутствие конкретного значения. Используется для функций, которые не возвращают значений button.onclick = () => void doSomething();
Null Null Используется, когда переменная определена (например, строка или число), а значение неопределенно. let x: null = null; console.log(x);
Undefined Undefined Используется для всех неинициализированных переменных let x: undefined = undefined; console.log(x);

Большинство из этих типов соотносится с примитивными типами из JavaScript.

{} – комплексный объект, которому можно определить свойства или индикатор:

{name: string, age: number} // объект с атрибутами имени и возраста.

или

let person = {name:»Kira», age:25}; console.log(person.name); // Другой вариант получения свойства. Результат одинаковый console.log(person[«name»]);

Рассмотрим пример кода:

let person = { name: «Kira», age: 25 }; person = { name: «Ira» };

Во второй строке мы получим ошибку, поскольку объект person имеет два свойства name и age. Должно быть соответствие по названиям, количеству и типу свойств.

Array используется для определения типов элементов массива.

Указать тип можно двумя способами:Array и T[ ]

Массив чисел Number[ ]

Пример:

let list: number[] = [11, 22, 33]; let colors: string[] = [«red», «green», «blue»]; console.log(list[0]); // 11 console.log(colors[1]); // green

Массив строкArray :

let names: Array = [«Kira», «Ira», «Vera»]; console.log(names[1]); // Ira

Enum – перечисление, возможность дать имена наборам числовых значений:

enum Day { Monday, Friday, Saturday, } let b: Day = Day.Friday

Кортежив TypeScript имеют фиксированное количество элементов определенных типов:

// Declare a tuple type let x: [string, number]; // Initialize it x = [«hello», 10]; // OK // Initialize it incorrectly x = [10, «hello»]; // Error

Компилятор выдаст приблизительно такие сообщения об ошибках:Type ‘number’ is not assignable to type ‘string’.

Type ‘string’ is not assignable to type ‘number’.

// Определение кортежа – кортеж состоит из двух элементов – строки и числа let user: [string, number]; // Инициализация кортежа user = [«Kira», 25]; // Неправильная инициализация – переданные значения не соответствуют типам по позиции //userInfo = [25, «Kira»]; // Ошибка // Использование кортежа console.log(user[1]); // 25 user[1] = 26; // а тут мы поменяли значение 25 на 26

Параметры функций подразделяются на параметры по умолчанию, однотипные и необязательные.

  1. По умолчанию function NAME_F (NAME_P:тип = “х”):

Пример:

// Определение функции function add(a: number, b: number): number { return a + b; } // Вызов функции let result1 = add(1, 2); // результат 3

Для определения классов поддерживаются модификаторы контроля доступа public, protected и private:

Класс, название, атрибуты:

class User { name: string; surname: string; year: number; }

Тот же класс, вместе с модификаторами:

class User { protected name: string; public surname: string; private _year: number; }Идентификаторы в TypeScript – это имена переменных, функций и других элементов кода. Идентификаторы могут содержать буквы, цифры и некоторые спецсимволы (‘_’ и ‘$’). Цифра не может стоять в начале идентификатора.

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

Например, Name_one, Name_1, Name1, Name$.

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

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

Пишем приложение на TypeScript

Теперь создадим простой калькулятор и посмотрим, как отличается код для него на JS и на TS. Сначала сверстаем форму:

+

Здесь два поля для ввода чисел, кнопка, которая запускает скрипт и элемент для вывода результата:

Код TypeScript выглядит так:

//Получая элемент, мы можем указать, какого он типа//В данном случае — поле ввода//Это говорит, что полученный элемент точно содержит свойства value и valueAsNumber, которые нам нужны//Если мы не укажем тип HTMLInputElement, компилятор не поймет, что у этого элемента есть свойство value, и откажется компилироватьconst num1 = document.getElementById(«num1»); const num2 = document.getElementById(«num2»); //Можно и не указывать тип элемента, если вам не нужны какие-то специфические свойстваconst result = document.getElementById(«result»); const btn = document.getElementById(«btn»); //Пока ещё не все современные браузеры поддерживают стрелочные функции, но компилятор TypeScript заменит её на обычную анонимную функцию//При условии, что в конфиге указана спецификация es5 btn.addEventListener(«click», (e) => { Sum(); }); functionSum() { //В эту переменную можно добавить только числовое значение//Однако ввод всё равно стоит проверять, потому что пользователь может ввести что угодно вместо числаlet sum : number = num1.valueAsNumber + num2.valueAsNumber; //Тип свойства innerHTML — string, поэтому мы должны конвертировать переменную sum в строку result.innerHTML = sum.toString(); }

А скомпилированный JS-код для такого калькулятора выглядит вот так:

var num1 = document.getElementById(«num1»); var num2 = document.getElementById(«num2»); var result = document.getElementById(«result»); var btn = document.getElementById(«btn»); btn.addEventListener(«click», function (e) { Sum(); }); functionSum() { var sum = num1.valueAsNumber + num2.valueAsNumber; result.innerHTML = sum.toString(); }

Источники
  • https://proglib.io/p/samouchitel-dlya-nachinayushchih-kak-osvoit-typescript-s-nulya-za-30-minut-2021-03-12
  • https://webformyself.com/typescript-izuchaem-s-nulya/
  • https://habr.com/ru/post/258957/
  • https://okdk.ru/chto-takoe-typescript-i-pochemu-razrabotchiki-dolzhny-ego-poprobovat/
  • https://skillbox.ru/media/code/typescript_kak_s_nim_rabotat_i_chem_on_otlichaetsya_ot_javascript/

tett
Зарплатто.ру - сайт о зарплатах и доходах, деньгах и финансах