Как подключить файл typescript к html
В конце 2012 года Microsoft представила TypeScript, типизированный суперсет для JavaScript, который компилируется в обычный JavaScript. TypeScript фокусируется на предоставлении полезных инструментов для крупномасштабных приложений путем реализации функций, таких как классы, аннотации типов, наследование, модули и многое другое! В этом уроке мы начнем с TypeScript, используя простые примеры кода с укусом, скомпилируем их в JavaScript и просмотрим мгновенные результаты в браузере.
Установка инструментов
Возможности TypeScript применяются только во время компиляции.
Вы настроите свою машину в соответствии с вашей конкретной платформой и потребностями. Пользователи Windows и Visual Studio могут просто загрузить плагин Visual Studio. Если вы работаете в Windows и не имеете Visual Studio, попробуйте Visual Studio Express для Интернета. Опыт TypeScript в Visual Studio в настоящее время превосходит другие редакторы.
Если вы работаете на другой платформе (или не хотите использовать Visual Studio), все, что вам нужно, это текстовый редактор, браузер и пакет npm для TypeScript для использования TypeScript. Следуйте инструкциям по установке:
- Установка диспетчера пакетов node (npm)
- Глобально установите TypeScript пакет npm:
- Любой современный браузер: для этого учебника мы используем Chrome.
- Любой текстовый редактор: для этого учебника используется Sublime Text
- Модуль подсветки синтаксиса для текстовых редакторов
Готово; мы готовы сделать простое приложение «Hello World» в TypeScript!
Hello World в TypeScript
TypeScript является надмножеством Ecmascript 5 (ES5) и включает функции, предлагаемые для ES6. Из-за этого любая программа JavaScript уже является программой TypeScript. Компилятор TypeScript выполняет локальные преобразования файлов в программах TypeScript. Следовательно, окончательный вывод JavaScript точно соответствует вводу TypeScript.
Сначала мы создадим базовый файл index.html и ссылку на внешний файл сценария:
Это простое приложение «Hello World»; поэтому давайте создадим файл с именем hello.ts . Расширение *.ts обозначает файл TypeScript. Добавьте следующий код в hello.ts :
Затем откройте интерфейс командной строки, перейдите к папке, содержащей hello.ts , и запустите компилятор TypeScript с помощью следующей команды:
Команда tsc является компилятором TypeScript и сразу генерирует новый файл hello.js . В нашем приложении TypeScript не используется синтаксис, специфичный для TypeScript, поэтому мы видим тот же самый код JavaScript в hello.js , который мы написали на hello.ts .
Круто! Теперь мы можем изучить возможности TypeScript и посмотреть, как это может помочь нам поддерживать и создавать широкомасштабные приложения JavaScript.
Аннотации type
Аннотации типа являются дополнительной функцией, которая позволяет нам проверять и выражать наше намерение в программах, которые мы пишем. Давайте создадим простую функцию area() в новом файле TypeScript, называемом type.ts
Затем измените источник скрипта в index.html на type.js и запустите компилятор TypeScript с помощью t sc type.ts . Обновите страницу в браузере, и вы увидите следующее:
Как показано в предыдущем коде, аннотации типа выражаются как часть параметров функции; они указывают, какие типы значений вы можете передать функции. Например, параметр shape обозначается как строковое значение, а width и height - это числовые значения.
Аннотации типов и другие функции TypeScript применяются только во время компиляции. Если вы передадите какие-либо другие типы значений этим параметрам, компилятор даст вам ошибку времени компиляции. Такое поведение чрезвычайно полезно при создании крупномасштабных приложений. Например, давайте намеренно передать строковое значение для параметра width :
Мы знаем, что это приводит к нежелательному результату, и компиляция файла предупреждает нас о проблеме со следующей ошибкой:
Обратите внимание, что, несмотря на эту ошибку, компилятор сгенерировал файл type.js . Ошибка не останавливает компилятор TypeScript от генерации соответствующего JavaScript, но компилятор предупреждает нас о потенциальных проблемах. Мы предполагаем, что width будет числом; передача чего-либо другого приводит к нежелательному поведению в нашем коде. Другие аннотации типа включают bool или даже any .
Интерфейсы
Давайте расширим наш пример, включив интерфейс, который далее описывает форму как объект с дополнительным свойством color . Создайте новый файл с именем interface.ts и измените источник скрипта в index.html , чтобы включить interface.js . Введите следующий код в interface.ts :
Интерфейсы - это имена, присвоенные типам объектов. Мы можем не только объявить интерфейс, но и использовать его как аннотацию типа.
Компиляция interface.js не приводит к ошибкам. Чтобы вызвать ошибку, добавим еще одну строку кода в interface.js с формой, которая не имеет свойства имени и посмотрим результат в консоли браузера. Добавьте эту строку в interface.js :
Теперь давайте посмотрим на ошибку. Это:
Мы видим эту ошибку, поскольку объект, переданный в area() , не соответствует интерфейсу Shape ; для этого требуется свойство name.
Стрелочные функции
Понимание сферы действия ключевого слова this является сложной задачей, и TypeScript упрощает его, поддерживая выражения стрелочных функций, новую возможность, обсуждаемую для ECMAScript 6. Стрелочные функции сохраняют значение this , что значительно упрощает запись и использование функций обратного вызова. Рассмотрим следующий код:
this.name в строке 7 будет явно пустым, как показано в консоли браузера:
Взгляните на созданный файл JavaScript. Вы увидите, что компилятор ввел новую переменную var _this = this; , и использовал ее в функции обратного вызова setTimeout() для ссылки на свойство name .
Классы с общедоступными и частными модификаторами доступа
TypeScript поддерживает классы, и их реализация тесно соответствует предложению ECMAScript 6. Давайте создадим еще один файл с именем class.ts , и рассмотрим синтаксис класса:
Вышеуказанный класс Shape имеет два свойства, area и color , один конструктор (точно названный constructor() ), а также метод shoutout() . Скоуп аргументов конструктора ( name , width и height ) являются локальными для конструктора. Вот почему вы увидите ошибки в браузере, а также компилятора:
Любая программа JavaScript уже является программой TypeScript.
Затем давайте рассмотрим public и private модификаторы доступа. Доступ к публичным членам можно получить повсюду, тогда как частные члены доступны только в рамках класса. Разумеется, в JavaScript нет возможности для обеспечения конфиденциальности, поэтому доступность для частного доступа обеспечивается только во время компиляции и служит предупреждением первоначальному намерению разработчика сделать его конфиденциальным.
В качестве иллюстрации добавим модификатор public к аргументу конструктора, name и модификатор private к color . Когда мы добавляем public или private доступность к аргументу конструктора, этот аргумент автоматически становится членом класса с соответствующим модификатором доступности.
Наследование
Наконец, вы можете расширить существующий класс и создать из него производный класс с ключевым словом extends . Давайте добавим следующий код к существующему файлу class.ts и скомпилируем его:
Несколько вещей происходят с производным классом Shape3D :
- Поскольку он получен из класса Shape , он наследует свойства area и color .
- Внутри метода конструктора метод super вызывает конструктор базового класса Shape , передавая значения name , width и height . Наследование позволяет нам повторно использовать код из Shape , поэтому мы можем легко вычислить this.volume с унаследованным свойством area .
- Метод shoutout() переопределяет реализацию базового класса, а новый метод superShout() напрямую вызывает метод buout() базового класса, используя ключевое слово super .
Имея только несколько дополнительных строк кода, мы можем легко расширить базовый класс, чтобы добавить более конкретные функции и сделать наше намерение известным с помощью TypeScript.
Ресурсы TypeScript
Несмотря на чрезвычайно молодой возраст TypeScript, вы можете найти много полезных ресурсов в Интернете (включая полный курс, который подходит к Tuts + Premium!). Обязательно проверьте их:
Мы только начинаем
Попробовать TypeScript легко. Если вам нравится более статически типизированный подход для больших приложений, то функции TypeScript будут применять привычную, дисциплинированную среду. Хотя его и сравнивают с CoffeeScript или Dart, TypeScript отличается тем, что он не заменяет JavaScript; он добавляет функции JavaScript.
Рабочей средой станет редактор Visual Studio Code и браузер Chrome, который будет использоваться для отладки. Классами, строгой типизацией и абстракцией нас обеспечит Typescript — транспилируемый (т.е. преобразующийся в Javascript) язык от Microsoft. В качестве игрового HTML5-фреймворка выступает Phaser.
Начнём обустраиваться. Процесс первоначальной настройки не быстрый и не совсем легкий, но его нужно сделать только один раз. Все, что написано далее, я проверял на Windows 7 x64.
1. Устанавливаем необходимые программы.
2. Устанавливаем пакеты для NodeJS.
VS Code изначально готов к работе с NodeJS, так что нам остаётся только установить нужные пакеты. Включаем консоль (через Пуск — «Стандартные» -> «Командная строка»; я предпочитаю клавиши Win+R -> cmd). Возможно потребуется запустить консоль от имени администратора. Вводим следующие команды:
Дальнейшие действия я буду производить внутри VS Code на примере движка Phaser, но аналогично можно сделать для любого другого (или вообще не использовать готовый движок, но всё равно иметь преимущества перед чистым JS, которые я указал в начале статьи).
3. Для начала создадим костяк проекта
А. Создаём папку проекта, и внутри следующую структуру
bin/ — папка, которую впоследствии и будем выкладывать в интернет
bin/assets/ — ресурсы игры (звуки, картинки)
bin/js/ — в эту папку typescript будет транспилироваться в javascript
src/ — исходный код нашего проекта (на Typescript)
tsDefinitions/ — файлы аннотаций типов, нужны для автодополнения (см. далее)
Б. Интеграция движка Phaser в проект
Скачиваем Phaser. Теперь переносим соответствующие файлы в проект (файл phaser ---> файл проекта):
- phaser/build/phaser.js ---> bin/js/phaser.js
- phaser/typescript/box2d.d.ts ---> tsDefinitions/box2d.d.ts
- phaser/typescript/p2.d.ts ---> tsDefinitions/p2.d.ts
- phaser/typescript/pixi.d.ts ---> tsDefinitions/pixi.d.ts
- phaser/typescript/phaser.d.ts ---> tsDefinitions/phaser.d.ts
Первый файл — сам движок. Когда игра будет закончена, его можно заменить на phaser.min.js, для меньшего размера. Пока нам нужен именно этот файл, так как его удобнее использовать при отладке.
Далее четыре файла — это аннотации типов для phaser, который будет использовать typescript.
Аналогичные действия можно использовать для любого другого движка.
В. Создаём файл стартовую страницу игры (bin/index.html)
Обратите внимание на теги script, включающие движок phaser.js и код нашей игры game.js, который уже скоро появится. :) Элемент div с идентификатором content будет при написании кода (пункт 6) использоваться как игровая область.
4. Конфигурация для Typescript
Теперь нам нужно указать редактору, как образом мы хотим преобразовывать Typescript-код в JS-код. Для этого создадим файл tsconfig.json:
<
«compilerOptions»: <
«target»: «es5»,
«sourceMap»: true,
«outFile»: «bin/js/game.js»
>
>
Здесь мы указываем, что все *.ts файлы в проекте нужно транспилировать в javascript версии ES5, и собрать в один файл, располагающийся в bin/js/game.js. Опция «sourceMap» нужна для создания карты исходных файлов, что позволит нам осуществлять отладку через файлы Typescript. Как непосредственно запустить транспиляцию мы узнаем позже.
5. Запуск локального сервера
Теперь нужно запустить локальный сервер из папки bin/. Для этого создадим «задачу» в VS Code, выполняющую простую команду в консоли. Выбираем из меню «Задачи» -> «Настроить задачи». В дереве проекта создастся файл .vscode/tasks.json, содержимое которого меняем на:
6. Наконец-таки код игры!
Напишем простую заглушку — код нашей игры. Программа будет выводить изображение в центре игровой области, на цветном фоне. Создадим файл src/Game.ts.
Не забудьте закинуть cat.jpg в bin/assets, так как код использует данный ресурс.
class SimpleGame
<
game: Phaser.Game;
preload()
<
this.game.load.image( 'cat', «assets/cat.jpg» );
>
create()
<
this.game.stage.backgroundColor = 0xaa22ff;
let logo = this.game.add.sprite( this.game.world.centerX, this.game.world.centerY, 'cat' );
logo.anchor.setTo( 0.5, 0.5 );
>
>
// when the page has finished loading, create our game
window.onload = () => <
let game = new SimpleGame();
>
В Game.ts создаём класс SimpleGame для нашей игры, который при создании (constructor()) запускает движок в div элементе с идентификатором «content», устанавливает размер 800х600 пикселей, и указывает, какие функции выполнять при предзагрузке и первоначальном старте игры (preload() и create()).
В preload() мы загружаем ресурсы и производим первоначальную настройку. Загружаем файл «assets/cat.jpg» в движок под ключом «cat».
Create() вызывается один раз при запуске игры. Устанавливаем цвет фона. Выводим спрайт, загруженный под ключом «cat», в центре экрана.
В последних строках (window.onload) указываем, что делать при загрузке веб-страницы (она происходит ДО загрузки самой игры). В данном случае создаём экземпляр класса SimpleGame.
Теперь узнаем, как производить js-код и отладку.
7. Транспиляция кода
Время создать javascript — код! Для этого нажимаем Ctrl+Shift+B (в меню это «Задачи» -> «Запустить задачу сборки»). На основе нашего файла конфигурации tsconfig.json редактор предлагает нам два варианта — «сборка» и «отслеживание». Первый — единоразовая транспиляция. Все *.ts файлы будут переведены в js и собраны в один файл game.js, согласно файлу конфигурации. Второй вариант — такой же, только теперь при любом изменении и сохранении исходного кода сборка будет запускаться автоматически.
Теперь, запустив сервер, и перейдя в браузере по ссылке «localhost:8080» мы можем увидеть картинку и надпись «Simple game». :)
Устанавливаем расширение — отладчик. Нажимаем Ctrl+Shift+X, что откроет менеджер расширений, ищем и ставим Chrome Debugger. Перезапускаем редактор.
По нажатию F5 в редакторе запускается отладка. В первый раз редактор не знает, какой именно инструмент для отладки использовать, поэтому мы должны сами указать ему. При первом нажатии F5 в проекте будет создан файл конфигурации .vscode/launch.json, содержимое которого меняем на:
Теперь нам доступен весь функционал стандартного дебаггера! Можем устанавливать точки останова, использовать watch-выражения и тд из typescript-кода.
Пара советов
Если после транспиляции игра на странице сервера не обновилась, зажмите Shift и в браузере «Перезагрузить страницу», чтобы он не использовал кэшированную версию страницы.
Иногда при отладке не срабатывают точки останова, особенно если они находятся в начале выполнения кода (например, сразу после загрузки страницы) нужно обновить страницу в открывшемся браузере, так как дебаггер ещё не успел запуститься.
Используйте флаг «strict»: true в файле tsconfig.json. Строгий режим проверки кода спасет от незаметных ошибок.
Ctrl + Пробел в редакторе предлагает варианты автодополнения. Можно использовать при редактировании как файлов с исходным кодом, так и файлов конфигураций.
Вот так, с помощью нехитрых приспособлений.
После настройки типичный рабочий процесс будет выглядеть так:
- Создание typescript кода в папке src. Можно создавать несколько файлов, транспилятор преобразует все файлы в один — game.js.
- Спрайты, аудиофайлы и тд перемещаем в bin/assets.
- Запуск локального сервера через «Запуск задачи» -> «Run Server At \bin». За состоянием сервера можно следить в окне «Terminal» редактора.
- Транспиляция Typescript через Ctrl+Shift+B.
- Открытие страницы с игрой и подключение отладчика через нажатие F5.
- После завершения работы над проектом — публикация папки bin/.
Спасибо за внимание!
chrome — 63.0
vs code — 1.18
nodejs — 8.9.3
phaser — 2.9.3
typescript — 2.6.2
Для установки связи с внешними файлами скриптов javascript в TS служат декларативные или заголовочные файлы. Это файлы с расширением .d.ts , они описывают синтаксис и структуру функций и свойств, которые могут использоваться в программе, не предоставляя при этом конкретной реализации. Их действие во многом похоже на работу файлов с расширением .h в языках C/C++. Они выполняют своего рода роль оберток над библиотеками JavaScript.
Рассмотрим, как мы можем использовать заголовочные файлы. Иногда в программах на javascript используются глобальные переменные, которые должны быть видны для всех функций приложения. Например, пусть на веб-странице (или во внешнем подключаемом файле javascript) в коде js определена переменная:
В данном случае для простоты переменная определена веб-странице, хотя она также могла быть определена во внешнем подключенном js-файле.
И, допустим, мы хотим использовать эту переменную message в коде TypeScript в файле app.ts:
При запуске приложения компилятор TS не сможет скомпилировать программу, так как для кода TS глобальная переменная пока не существует. В этом случае нам надо подключать определение глобальной переменной с помощью декларативных файлов. Для этого добавим в проект новый файл, который назовем globals.d.ts и который будет иметь следующее содержимое:
С помощью ключевого слова declare в программу на TS подключается определение глобальной переменной.
То есть у нас получится следующая структура проекта:
Компиляция
Если мы компилируем, передавая компилятору в консоли название файла:
То в этом случае компилятор не найдет автоматически файл globals.d.ts. В этом случае нам надо в файле app.ts явно указать расположение файла globals.d.ts с помощью директивы reference
Если же мы полагаемся на файл конфигурации tsconfig.json, просто выполняя команду
то директиву /// <reference path="globals.d.ts" /> можно не указывать.
Подобным образом мы можем подлюкчать другие компоненты кода JavaScript - функции, объекты, классы. Рассмотрим их подключение.
Функции
Пусть на веб-странице в коде js объявлены две следующие функции:
Функция hello() выводит значение переменной message на консоль, а функция sum() возвращает сумму двух чисел.
И, допустим, в коде TS мы хотим вызывать эти функции:
В этом случае подключение в файле globals.d.ts выглядело бы так:
Подключение объектов
Пусть в коде JavaScript есть следующий объект:
Используем этот объект в коде typescript:
В этом случае определение объекта в файле globals.d.ts выглядело бы так:
Подключени сложных объектов
Однако может возникнуть сложность с подключением более сложных объектов. Например, пусть есть такой объект javascript:
Для данного массива объектов в файле globals.d.ts мы можем определить соответствующий отдельному объекту интерфейс и подключить массив объектов некоторого интерфейса, который содержит два свойства X и Y:
И в TS мы сможем использовать этот массив:
Консольный вывод браузера:
Точка с координатами X = 10 Y = 34 Точка с координатами X = 24 Y = 65 Точка с координатами X = 89 Y = 12Подключение классов
Рассмотрим последний пример - подключение в typescript классов, определенных в javascript. Пусть в коде JavaScript определен следующий класс Person:
Для этого класса в файле globals.d.ts определим следующее объявление класса:
Для класса прописываем все его поля и методы, при этом методы (в том числе конструктор) не имеют реализации, для них только определяются параметры и их типы и тип возвращаемого значения.
Update 12 января 2021: Обновление webpack’а до 5 версии, а также изменения связанные с Eslint привели к необходимости обновить статью.
В данной статье поговорим о конфигурации webpack для сборки typescript приложения, рассмотрим локальную разработку и сборку приложения для продакшена.
Иногда появляются задачи, по разработке небольшого приложения, где не нужны современные фронтенд фреймворки. И как не был прост React или Vue, задачи обычно сводятся, что нужно сверстать страничку и добавить форму, которая будет отправлять данные на указанный endpoint.
В данном случае, TS/JS кода будет не больше 20 строк кода:
И разворачивать полноценный фреймворк нет смысла. Для данного кода можно отказаться от всех современных благ разработки, если бы не одно но — Необходимо сверстать страничку. А это значит, что нужен CSS препроцессор, нужна автоматическая перезагрузка при изменении кода, а также сборка и оптимизация кода.
И вместо того, чтобы использовать полноценный фреймворк можно сделать простую сборку на webpack.
Основные требования к сборке:
- Typescript — компиляция js
- Livereload — автоматическая перезагрузка
- SCSS — компиляция scss в css
- Html optimize — оптимизация html для prod версии
- Assets — правильные пути к используемым ресурсам (images, fonts, video и т.д)
Создание сборки
Для создания сборки создадим новый node проект:
Установка зависимостей
Добавим основные зависимости для webpack:
Так как необходимы лоадеры для typescript, обработки обычных файлов(assets), файлов стилей и html, добавим лоадеры:
Так как папки для dev и prod нужно чистить, добавим необходимые плагины:
И для контроля качества кода, добавим tslint и prettier:
Добавление конфигураций
Сначала добавим tsconfig:
Конфигурация postcss:
Отметим, что работа с Eslint немного отличается от tslint. Если в Tslint’е можно создать универсальный конфиг, который будет применяться к каждому файлу, то в Eslint такой подход не пройдет. Eslint объединит все правила постарается их применить: правила для html + css + ts. Это все приведет к тому, что парсер будет падать с ошибками. Поэтому, все правила в eslint’е группируются по типам файлов и применяются в соответствии с группами.
Пример конфига для eslint’а:
Настройка webpack
Общая настройка будет следующей:
Как можно увидеть из конфигурации, все достаточно просто. Для настройки dev-server’а:
Plugin CopyWebpackPlugin копирует нужные asset’ы:
Плагин HtmlWebpackPlugin использует шаблон для интеграции js и css:
Плагин MiniCssExtractPlugin сохраняет стили в отдельный файл:
Читайте также: