TypeScript – это язык, который становится все более популярным и востребованным. Созданный на основе JavaScript, TypeScript добавляет в JavaScript функции, которые помогают нам писать код, который с меньшей вероятностью будет содержать ошибки и который легче поддерживать.
Современные веб-приложения становятся все более сложными, и для решения этой растущей сложности JavaScript необходимо было обновить. Было несколько попыток улучшить JavaScript, и TypeScript стал неоспоримым победителем.
TypeScript – это расширенный набор JavaScript, что означает, что это JavaScript с дополнительными функциями. Весь существующий код JavaScript по определению также является кодом TypeScript.
Настройка TypeScript
Веб-браузеры и NodeJS не понимают код TypeScript. Сначала он должен быть преобразован в JavaScript с помощью процесса, называемого компиляцией. Компилятор TypeScript, который выполняет эту компиляцию, называется tsc. Давайте посмотрим, как мы можем это использовать.
В рамках проекта NPM
Мы можем добавить TypeScript локально в проект npm следующим образом:
mkdir test-app cd test-app npm init -y npm install --save-dev typescript npx tsc --init
Файл с именем tsconfig.json будет создан после запуска tsc –init и помещен в корневой каталог проекта. Этот файл содержит настройки и опции для компилятора TypeScript (tsc).
В идеале мы будем хранить наши файлы TypeScript в одном каталоге, а все наши сгенерированные файлы JavaScript будут помещаться в их собственный каталог. Давайте создадим каталог src для файлов TS и каталог dist для файлов JS.
mkdir src dist
Мы можем указать tsc, где найти наши файлы TS и где разместить наши файлы JS, отредактировав два поля в файле tsconfig.json:
Откройте проект в редакторе кода и внесите вышеуказанные изменения. Наконец, мы можем добавить скрипт «build: dev» в наш файл package.json:
{ "name": "from-js-to-ts", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build:dev": "tsc --watch --preserveWatchOutput", "start": "node dist/index.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "typescript": "^3.7.3" } }
Компилятор настроен на работу в режиме наблюдения, чтобы перекомпилировать наш код при сохранении изменений. Я также установил его, чтобы сохранить вывод консоли, что является личным предпочтением, которое вы можете удалить. Также был добавлен стартовый скрипт, чтобы мы могли запустить быстрый тест.
Создайте файл index.ts внутри каталога src:
touch src/index.ts echo "console.log('hello');" > src/index.ts
Затем скомпилируйте код и запустите его:
npm run build:dev (In a separate terminal window or tab) npm start
Мы вернемся к этому тестовому приложению позже. А пока убейте сервер, нажав Ctrl C в терминале.
В рамках реактивного проекта
Мы можем создать новый проект React, настроенный с помощью TypeScript, используя инструмент create-реагировать-приложение (CRA):
npx create-react-app my-app --template typescript (OR) yarn create react-app my-app --template typescript
Все уже настроено с помощью CRA. Мы можем запустить проект так же, как обычный проект React: запуск пряжи или запуск npm. Никакой специальной настройки не требуется, например, редактирование файла tsconfig.json.
Типы
В JavaScript тип переменной определяется динамически во время выполнения кода, фазы, известной как время выполнения. Примерами распространенных типов являются число, строка и логическое значение. Тип переменной может изменяться в ходе работы приложения, вызывая непреднамеренные ошибки:
JavaScript – это слабо типизированный язык. TypeScript, напротив, строго типизирован, то есть тип переменной не может измениться во время выполнения:
TypeScript вводит фазу компиляции в наше приложение. На этом этапе компилятор ищет и идентифицирует несоответствия типов и ошибки. Этот процесс называется статической проверкой типов.
Современные веб-приложения большие и сложные со множеством движущихся частей. По-человечески невозможно обеспечить согласованность типов в нашем коде JavaScript. К счастью, TypeScript может сделать эту работу за нас.
Указание типа переменной
Хотя мы не указали явно тип для баланса в предыдущем примере, TypeScript смог определить его. Мы можем быть очевидными, указав тип после имени переменной:
// Basic types var trueOrFalse: boolean; var quantity: number; var message: string; var doNotKnowYet: undefined; var nothingness: null; var iCanBeAnything: any; // this is self-defeating! // Typed arrays var arrayOfStrings: string[]; var productPrices: number[];
Примитивы JavaScript имеют очевидные имена: логическое значение, число, строка, неопределенное значение, ноль. Массивы также могут быть набраны.
В TypeScript есть специальный тип, называемый any. Переменная, объявленная как тип any, может быть, как следует из ее названия, любого типа и, по сути, является обычной переменной JavaScript. любого следует избегать всякий раз, когда это возможно; в противном случае мы просто будем писать слабонабираемый код JavaScript.
Кортеж
Новый тип, который вводит TypeScript, называется кортежем. Примером кортежа являются координаты в трехмерном пространстве: (x, y, z). Мы могли бы создать кортеж для представления ответа от сервера:
Кортежи имеют фиксированное количество элементов, и мы можем указать разные типы для каждого элемента. Кортежи – это функция, распространенная во многих современных языках программирования, таких как Python, Go и Elixir.
Перечисления
Перечисление, или перечисление, представляет собой список констант с автоматически генерируемыми числовыми значениями:
Перечисления – это удобный способ создания констант. Первая константа начинается с 0, если не указано иное, и каждая последующая константа имеет значение на единицу больше предыдущей.
Перечисления доступны на многих языках, таких как Java и C #, и являются лучшей альтернативой строковым константам, потому что с ними гораздо быстрее работать (по техническим причинам, которые выходят за рамки данной статьи).
Указание нескольких типов
Можно указать, что переменная может иметь диапазон типов:
Это достигается с помощью типа объединения, который имеет вид: type_1 | type_2 | … | type_n. Использование объединенного типа требует осторожности, поскольку мы в основном возвращаемся к слабой типизации. Откройте ссылку на типы объединений, и вы найдете различные способы решения этой проблемы.
Помимо основных типов
Помимо примитивных типов у нас есть так называемые ссылочные типы: массив, функция и объект.
Объекты и Интерфейсы
Чтобы объявить тип для объекта, мы используем функцию TypeScript, называемую интерфейсом. В TypeScript интерфейсы описывают форму объекта. Давайте создадим два из них:
TypeScript использует типизацию утилит, чтобы определить, имеют ли объекты совместимые типы. Мы видим, что массив pets может принимать объекты Person, в данном случае – друга. Хотя friend – это объект типа Person, он также рассматривается как объект типа Pet, поскольку Person и Pet имеют одинаковую форму.
В английском языке есть выражение: если оно выглядит как утка, плавает как утка и крякает как утка, то это, вероятно, утка. Отсюда и название утка.
Классы
Классы TypeScript похожи на классы JavaScript, но поддерживают дополнительные функции. Классы, такие как интерфейсы, также могут использоваться для определения формы объекта. Вот типичное определение класса:
Мы определили ряд функций внутри нашего класса. Когда функция является частью определения класса, она называется методом. Мы немного поговорим об объявлении типов для функций и методов.
Мы видим, что некоторые вещи помечены как частные, другие общедоступны, а одна защищена. Они известны как спецификаторы видимости, и их целью является ограничение доступа к свойствам и методам. Они являются важной частью объектно-ориентированного проектирования, что является существенной темой и выходит за рамки данной статьи.
вид был объявлен как свойство только для чтения. readonly похож на const, но используется внутри интерфейсов, классов и типов, которые мы скоро представим.
Функции (и методы)
Как мы видим из предыдущего примера, мы можем определять типы не только для параметров функции, но и для ее возвращаемого типа. Взгляните на следующие примеры:
TypeScript также имеет тип void. Если функция не имеет возвращаемого значения, мы можем пометить ее как возвращающую void. Это часто встречается в таких языках, как C, C ++ и Java.
Указание неизвестного типа
Объединение типов – это здорово, если мы заранее знаем возможные типы переменной, но что если мы не знаем? TypeScript также заимствует из других языков функцию под названием generics. Обобщения позволяют нам указать тип переменной.
Давайте создадим два стековых класса. Стеки – это структура данных «последний пришел – первый вышел» (LIFO):
Наш первый стек ограничен только способностью обрабатывать числа. Если бы нам нужен был стек строк, нам пришлось бы дублировать наш стек и менять каждый экземпляр числа на строку.
К счастью, есть лучший способ. Наш второй стек использует переменный параметр с именем T, который мы можем указать по мере необходимости:
Общий параметр часто называют T по соглашению. В коде TypeScript K и V также распространены.
Массивы с генериками
Есть еще один способ создать типизированный массив с обобщениями. Взгляните на модифицированную версию нашего стекового класса, которая была переименована в просто Stack:
Эта форма встречается часто, и вы обязательно столкнетесь с ней.
Возможно, вы заметили, что эта строка кода возвращает this.items.pop () как T; и задавался вопросом, что это значит. Это называется приведением типов, которое является преобразованием одного типа в другой. Лучше всего избегать приведения типов. Я использую его только в этих примерах, чтобы сделать код максимально коротким, избегая проверки ошибок (а именно, ошибки переполнения стека).
Еще один способ объявить тип
Мы можем использовать ключевое слово type для объявления нового типа:
Первая функция, getPatient1, трудна для чтения, потому что ее тип возвращаемого значения является объектом. Мы можем очистить код, объявив форму возвращаемого типа отдельно. Обратите внимание на то, насколько чистым и читаемым является getPatient2.
Ключевое слово type можно использовать для объединения интерфейсов и создания так называемого распознаваемого типа объединения:
Это чрезвычайно полезно при создании типов действий для хранилища Redux, которые мы не будем здесь показывать для краткости. Проверьте это руководство с официального сайта Redux для более подробной информации.
Использование в реакции (необязательно)
Мы кратко рассмотрим способ использования TypeScript в приложении React. Откройте окно терминала и выполните следующие команды, чтобы создать новое приложение React:
npx create-react-app my-app --template typescript cd my-app npm start
Откройте проект в редакторе кода, затем откройте файл src / app.tsx. Обычно файл TypeScript заканчивается расширением .ts. Реагирующие компоненты, создающие JSX, должны заканчиваться расширением .tsx.
Замените код в src / app.tsx следующим:
import React from 'react'; import logo from './logo.svg'; import './App.css'; interface AppProps { name: string } const App: React.FC<AppProps> = ({ name }) => { return ( <div className="App"> Hello, {name}! </div> ); } export default App;
Наш компонент App – это функциональный компонент React, способный принимать универсальный параметр. Этот параметр используется для описания формы объекта реквизита компонента.
Мы также должны передать значение для имени. Откройте src / index.tsx и передайте какое-нибудь имя:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(<App name={"TypeScript Master"} />, document.getElementById('root')); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();
Сохраните все изменения, и вы должны увидеть следующее в браузере:
Убейте сервер, нажав Ctrl C в терминале.
Компилятор TypeScript может быть привередливым. Иногда он будет думать, что наш код неправильный, особенно если мы делаем слишком много изменений и часто сохраняем. Просто убейте сервер разработки с помощью Ctrl C и перезапустите его.
Использование в Node
Предыдущий раздел был предназначен для тех, кто уже знаком с React. Этот раздел не следует пропускать, поскольку он содержит важную информацию. Откройте ранее тестовое приложение в редакторе кода, затем откройте файл src / index.ts и удалите любой код в файле.
Теперь давайте воспользуемся модулем Node под названием os, чтобы получить информацию о нашей системе. Добавьте следующий код:
import os from 'os'; const cpuInfo = os.cpus(); console.log(cpuInfo);
Все, что делает этот код, это распечатывает информацию о процессорах вашей системы. Однако это не сработает:
Типы для модуля Node os должны быть предоставлены. Типы определяются в файлах, называемых файлами определения типов. Мы можем предоставить их, выполнив следующую команду:
npm install --save-dev @types/node
Команда устанавливает файлы определения типа для Node, внутри которого существует модуль os. После их установки сообщение об ошибке исчезнет. Убедитесь, что код работает, скомпилировав код и запустив его:
npm run build:dev (In a separate terminal window or tab) npm start
Вот некоторые из выводов, которые я получил. Ваш будет отличаться от моего.
Как правило, определения типов для любого данного пакета могут быть установлены с помощью следующих команд:
npm install --save-dev @types/PACKAGE_NAME (Abbreviated version) npm i -D @types/PACKAGE_NAME
Дальнейшее чтение
В TypeScript есть еще несколько функций, о которых вы можете узнать, изучив официальную документацию. Мы не охватывали пространства имен, декораторы или абстрактные классы. Официальная документация также содержит исчерпывающий список различных способов объявления типов в подавляющем множестве комбинаций.