tsx что за расширение
TypeScript и React с использованием create-react-app: пошаговое руководство по настройке вашего первого приложения
Из этого туториала вы узнаете, как быстро приступить к созданию приложений React с использованием TypeScript без необходимости какой-либо настройки с помощью create-react-app (CRA). Предположим, что на вашем компьютере уже установлены Node и NPM. Ваше приложение TypeScript/React будет работать сразу после установки без необходимости использовать CRA. Кроме того, вы узнаете, как создавать свои собственные компоненты и управлять props и state, используя TypeScript.
Установка с помощью create-react-app
create-react-app это инструмент командной строки, который позволяет разработчикам легко создавать новые приложения React с разумными настройками по умолчанию и нулевой конфигурацией.
Примечание. Этот шаг теперь необязательный. TypeScript можно установить с помощью npx, который будет показан в следующем разделе.
Инициализируйте свое приложение React с помощью TypeScript
Вызовите команду create-react-app с дополнительной опцией TypeScript, чтобы сгенерировать приложение React с использованием TypeScript в качестве синтаксиса JS по умолчанию.
Это создаст следующие файлы и структуру папок:
Ниже описание каждой части:
Изменения React под TypeScript
Чтобы использовать React с TypeScript, вы должны внести небольшие изменения в подходе создания стандартного приложения React.
Импорт React и ReactDOM
Вы можете заметить, что в компонентах по умолчанию используется следующий синтаксис:
С TypeScript вы больше не сможете делать стандартные импорты фида:
React экспортируется как модуль CommonJS, который не использует default export. На данный момент, не обязательно точно знать, почему, а просто знать, как вы должны импортировать React, чтобы он работал. Это также означает, что вы объявляете свои компоненты как:
Создание компонент
Вы определите интерфейс props для каждого из компонентов, которым вы передаете параметры. Вы определяете интерфейс объекта и где у каждого ключа может быть свой тип данных. Кроме того, вы можете объявить интерфейс для состояния (state) компоненты.
Функциональный компонент без хранения состояния
Чтобы продемонстрировать функциональный компонент с props, мы заменим заголовок
Начнем с импорта React. Затем мы объявляем интерфейс IProps с единственным параметром name. Мы указали что параметр необязательный, это задается симфолом “?”. Обозначение ключа как необязательного означает, что входной параметр может быть или string или undefined.
При создании компоненты Header, обратите внимание на React.SFC
. «SFC» обозначает функциональный компонент без сохранения состояния в прототип. Хотя это объявление не является обязательным, оно позволяет нам использовать defaultProps.
Далее, мы объявляем тип входного параметра как IProps, ссылающийся на созданный нами интерфейс.
Компонент класса
Чтобы показать основы компонента класса, мы заменим описание
в App.tsx на счетчик. Одним из ключевых различий между классом и функциональным компонентом является то, что компонент класса может поддерживать свое собственное состояние. Другим основным отличием является возможность доступа к методам жизненного цикла, описание которых выходит за рамки данного руководства.
Мы начнем с объявления интерфейса для IProps и IState. Будет необязательный счетчик вызовов счетчика, который будет определять значение приращения. Сам компонент будет вести подсчет, используя свое состояние.
Компонент объявлен с типами IProps и IState как class Description extends React.Component < и defaultProps объявлен как статическая переменная. State инициализируется со счетчиком 0.
Ваше create-react-app с компонентами TypeScript
Внутри нашего App.tsx мы импортируем только что созданные компоненты и заменяем HTML по умолчанию из CRA. Параметры name и countBy должны соответствовать типам, объявленным в дочернем компоненте. Поскольку props являются необязательными, они также могут быть undefined, и будет использоваться defaultProps.
И это все, что вам нужно для начала работы с TypeScript в React! Чтобы увидеть, как работает ваше приложение запустите следующую команду в консоли:
TypeScript: как с ним работать и чем он отличается от JavaScript
Frontend-разработка шагнула далеко за пределы JavaScript. Разбираемся, что такое TypeScript и почему его так любят.
На JavaScript написаны веб-интерфейсы практически всех сайтов. Однако не все его любят, а альтернатив почти нет. Единственный конкурент JS — WebAssembly, однако за несколько лет своего существования он пока не смог стать достаточно популярным.
Из-за такого расклада у разработчиков остаётся два выхода:
И многие выбирают второе решение. Поэтому за последние годы появилось сразу несколько языков-надстроек над JavaScript:
О последнем и пойдёт речь в этой статье. В 2019 году TypeScript стал одним из самых любимых языков программирования и попал в топ-10 по популярности:
Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.
Что такое TypeScript
TypeScript — это язык программирования, в котором исправлены многие недостатки JavaScript. Код на TypeScript выглядит почти так же, как и код на JS, и, если у вас есть опыт frontend-разработки, изучить TypeScript достаточно просто. Особенно учитывая, что вы можете писать JS-код прямо в TS-скриптах.
Код на TypeScript компилируется в JS и подходит для разработки любых проектов под любые браузеры — тем более что можно выбрать версию JS, в которую будет компилироваться код.
TypeScript — проект с открытым исходным кодом, поэтому он очень быстро развивается. Многое, что появляется в TS, позже переходит и в JavaScript: например, let и const, стрелочные функции и так далее.
Давайте разберём два главных преимущества TS перед JS.
Строгая типизация
Многие проблемы в JavaScript появляются из-за динамической типизации и в целом странного поведения типов данных:
В TypeScript типизация статическая, что избавляет от множества проблем. Есть числовой тип, строковый, логический и другие. Возможно описывать и свои типы данных, например, с помощью enum:
Улучшенное ООП
И в JS, и в TS есть поддержка объектно-ориентированного программирования: классы, объекты, наследование. Однако TypeScript шагнул чуть дальше и использует больше возможностей ОПП. В том числе, например, интерфейсы:
Другой большой плюс — модификаторы доступа. Их в TypeScript три: public, private и protected. Вот пример их использования:
Также есть и другие возможности:
В будущем всё это может появиться и в JavaScript, но браузеры начнут поддерживать такие возможности ещё очень нескоро.
Минусы TypeScript
Разработчики любят этот язык, а некоторые крупные проекты уже переходят на него. Например, популярный фреймворк Angular.JS. Но этого всё равно недостаточно, чтобы он стал таким же востребованным, как JavaScript. Это связано с тем, что разработка веб-приложения на TypeScript стоит дороже и отнимает больше времени.
Особенно если необходимо использовать какую-нибудь библиотеку или фреймворк, которые не портированы на TS. В этом случае разработчикам придётся самостоятельно описывать сигнатуры (указывать типы данных) всех функций и методов — достаточно длительный процесс, учитывая размеры современных библиотек.
Также порог входа в TypeScript выше — чтобы использовать его преимущества, важно знать типы данных и объектно-ориентированное программирование.
Установка TypeScript
Чтобы использовать TypeScript, установите сначала Node.JS. Как это сделать, можете прочитать в нашей статье. После этого введите в консоли команду:
Если всё пройдёт успешно, то в папке появится файл app.js, который и подключим к странице.
В compilerOptions хранятся все параметры для компилятора:
Пишем приложение на TypeScript
Теперь создадим простой калькулятор и посмотрим, как отличается код для него на JS и на TS. Сначала сверстаем форму:
Здесь два поля для ввода чисел, кнопка, которая запускает скрипт и элемент для вывода результата:
Код TypeScript выглядит так:
А скомпилированный JS-код для такого калькулятора выглядит вот так:
Заключение
Несмотря на то что в TypeScript очень достойный синтаксис, JavaScript ещё долго будет доминировать во frontend-разработке. Поэтому его в любом случае нужно знать, даже если он вам не нравится.
Если вы только приступаете к изучению программирования, то начинать с TypeScript будет сложно. Чтобы подготовиться, вы можете записаться на наш курс по frontend-разработке — вы освоите HTML, CSS, JS и его популярные фреймворки.
⚛️ 12 советов по внедрению TypeScript в React-приложениях
Сергей Кравченко
Зачем использовать TypeScript в React?
React – это JavaScript-библиотека с открытым исходным кодом для создания пользовательских интерфейсов, а TypeScript – типизированное надмножество JavaScript. Объединяя их, мы создаем пользовательские интерфейсы, используя типизированную версию JavaScript. Это означает большую безопасность и меньшее количество ошибок, отправляемых во внешний интерфейс.
Не существует единственного правильного способа написания кода React с использованием TypeScript. Как и в случае с другими технологиями, если ваш код компилируется и работает, вы, вероятно, что-то сделали правильно.
Подготовка компонентов к совместному использованию с помощью TypeScript
Bit.dev стал популярной альтернативой традиционным библиотекам компонентов, поскольку он предлагает способ собрать и поделиться отдельными компонентами из любой кодовой базы.
Создавая проекты с использованием React с TS, вы убедитесь, что ваши компоненты легко понятны другим разработчикам. Это отличный способ написать поддерживаемый код и оптимизировать совместную работу команды.
Настройка проекта и tsconfig.json
Самый быстрый способ запустить приложение React/TypeScript – использовать create-react-app с шаблоном TypeScript:
tsconfig.json это файл конфигурации TypeScript. Файл содержит первоначальные настройки, ниже приведем несколько параметров с пояснениями:
Enums
Enums определяет набор связанных констант как часть единой сущности.
Интерфейсы и типы
Что следует использовать – интерфейсы или псевдонимы типов? Хотя эти сущности концептуально различны, на деле они очень похожи:
Единственная функция интерфейсов, которую не делают псевдонимы типов – это объединение деклараций.
Расширение элементов HTML
Иногда ваши компоненты работают как собственные HTML-элементы. В таких случаях лучше определить тип компонента как собственный элемент HTML или его расширение.
Типы событий
React имеет собственный набор событий, поэтому вы не можете напрямую использовать события HTML. Однако у вас есть доступ к событиям пользовательского интерфейса. Убедитесь, что ссылаетесь на них напрямую или просто не забудьте импортировать их из React следующим образом:
Мы также можем использовать для ограничения элементов Generics с конкретным обработчиком событий.
Также можно применять объединения, чтобы разрешить повторное использование обработчика несколькими компонентами:
Определение интегрированного типа
Стоит упомянуть файлы index.d.ts и global.d.ts в React. Оба они устанавливаются, когда вы добавляете React в свой проект. Эти файлы содержат определения типов и интерфейсов: чтобы понять свойства или доступность конкретного типа, вы можете открыть эти файлы и просмотреть их содержимое.
index.d.ts » data-src=»https://media.proglib.io/posts/2021/01/20/bf2cf9687a65d39e7bd4506bfdbd507a.png» > index.d.ts
ESLint/Prettier
Чтобы гарантировать, что ваш код соответствует правилам проекта, а стиль согласован, рекомендуется настроить ESLint и Prettier :
Расширения и настройки кода VS
Следующий шаг по улучшению – автоматическое исправление и предварительная настройка кода при сохранении.
Установите ESLint и Prettier для VS Code. Это позволит ESLint легко интегрироваться с вашим редактором.
Вы можете принудительно установить тип или интерфейс начального значения состояния, например, так:
Однако, если начальное значение для вашего хука потенциально может быть null, то приведенный выше код не сработает. Для этих случаев TypeScript позволяет установить дополнительный тип:
Обработка событий формы
Расширение свойств компонентов
Можно расширить свойства, объявленные для одного компонента, и задействовать их в другом. Давайте сначала посмотрим, как использовать type:
Если вы использовали interface, то можно применить extends, чтобы расширить его, но придется внести пару изменений:
Сторонние библиотеки
Мы часто включаем сторонние библиотеки в проекты React и TypeScript. В таких случаях стоит посмотреть, есть ли пакет @types с определениями типов:
Итоги
Tsx что за расширение
За исключением типизации, написание шаблонов .tsx ничем не отличается от .jsx. Но так как при переходе с .jsx на .tsx возникает лишь один вопрос, как правильно писать те или иные виды компонентов в типизированном стиле, то данная глава будет отличаться от остальных и будет построена таким образом, чтобы общую информацию изучить по ходу детального рассмотрения каждого вида компонентов в отдельности. Кроме того, если раньше примеры кода были придуманы таким образом, чтобы помимо информативности, быть ещё и компактными, то в случаи с компонентами React, ничего поделать нельзя. Чтобы хоть как-то сгладить это, компоненты будут показываться небольшими частями, а уже после будет описываться важные-неочевидные моменты. Помимо этого, компоненты не будут иметь какой-то осмысленный характер. Если попытаться смоделировать, что-то, что можно продемонстрировать, то кода было бы в разы больше и сделало его менее понятным.
Также, возможности TypeScript, позволяют аннотировать языковые конструкции, как в классическом, так и в минималистическом стиле. В первом случае аннотацию типа содержит каждая конструкция. Во втором часть работы перекладывают на вывод типов. Так как предполагается, что читатели, если ещё не разрабатывают большие приложения, то всеми силами к этому стремятся. Поэтому все примеры в этой главе будут выполнены в классическом-максимальном стиле. Кроме того, стоит уточнить, что на момент написание этой главы используется React v16.4.1 и TypeScript 3.1 и если вы заметили несоответствие, которое может произойти из-за изменение в версиях выше указанных, то можете об этом сообщить всеми доступными способами, указанными в соответствующем разделе.
Следующее, на что стоит обратить внимание, это создание псевдонимов типа для всех объявленных ранее интерфейсов.
Затем, в теле класса компонента, происходит объявление полей, которые нужны для получение ссылок на нативные dom элементы ( ref ).
И прежде, чем перейти к рассмотрению кода в её теле, обязательно стоит пролить свет на один очень важный момент, связанный с аннотированием типов. Как было сказано в начале этой главы, все примеры являются классическими, с точки зрения типизации, но несмотря на это, всем, кто придерживается подобного подхода в повседневной разработке, рекомендуется делать отступления от правил, особенно в случаях с функциями передаваемых в качестве значения. В данном случае, подобное аннотирование, является явным перебором.
В случаях, когда параметры слушателя событий не требуются, лучше вообще опускать аннотацию типа и переложить эту заботу на вывод типов. К тому же, отсутствие аннотации даже подчеркнет тот факт, что важен лишь вызов этого слушателя.
Первая из них заключается в аннотировании параметра event, без аннотирования поля, которому присваивается слушатель событий. Из-за того, что этот код нельзя трактовать двусмысленно, не страдает его читаемость. Но кроме того, вывод типов сможет вывести тип для поля, если информацию о нем потребуется получить с помощью подсказок предоставляемых всеми современными idea.
Второй способ диаметрально противоположен первому и предполагает явно аннотировать поле, а не значение, в роли которого выступает слушатель событий.
Какой способ выбрать зависит лишь от конвенций по стилю кода установленного в команде и от специфики некоторых ситуации.
Далее стоит обратить внимание на код в теле слушателя событий, а именно операции асинхронного изменения состояния при помощи функции, также называемой “функциональным состоянием”. Именно этот способ был выбран по той причине, что он отлично дополняет сказанное относительно отступления от правил касающихся классического подхода при аннотировании языковых конструкций.
И напоследок осталось рассмотреть методы жизненного цикла компонента. Но так как в них нет ничего такого, на что читатели, к этому моменту, не смогли дать ответ самостоятельно, комментариев не будет.
Кроме того, что в React пользовательские компоненты могут расширять обобщенный класс Component
, они также могут использовать в качестве базового класса обобщенный класс PureComponent
Поскольку в React функциональные компоненты, которые чаще называют Stateless Components, являются обычной функцией, то объявлять их можно двумя способами, в виде обычной функции (Function Declaration) и в виде функционального выражения (Function Expression), декларация которого также разделяется на два варианта, аннотирование самой функции и декларирования ссылки на неё. Так как stateless компоненты очень компактные и в них нет ничего, что не было рассмотрено на предыдущих шагах, здесь будет приведен код всех трех вариантов, но особое внимание будет уделено последнему варианту.
Как уже было сказано, первый способ, аннотирование Function Declaration ничем не отличается от аннотирования обычных функций.
Второй способ, аннотирование функции, выступающей в качестве значения, также не отличается от аннотирования обычной функции.
Третий способ, на который стоит обратить внимание, заключается в аннотировании ссылки на компонент с помощью встроенного в систему типов React обобщенного типа StatelessComponent
. В нем нет ничего неординарного, поэтому о нём можно добавить, что в качестве аргумента типа, он ожидает тип, описывающий свойства ( props ) компонента.
Все варианты одинаковые и выбор зависит от личных предпочтений. Хотя я склоняюсь к третьему варианту.
Нет ничего особенного и в объявлении функциональной декларации (Function Declaration).
Но относительно функциональных компонентов, в роли которых выступают стрелочные функции (arrow function), без курьезов не обошлось. Дело в том, что на данный момент, TypeScript не поддерживает обобщенные стрелочные функции, в файлах, с расширением .tsx.
Кроме того, объявление обобщенного функционального компонента в виде функционального выражения тоже накладывает некоторые ограничения. В большинстве случаев, использование параметров типа предполагается использовать в обобщенном интерфейсе описывающим свойства ( props ) компонент. А это в свою очередь делает бессмысленным аннотацию идентификатора ссылающегося на функцию.
, но это бы сделало бессмысленным саму типизацию. Поэтому, единственный вариант объявления обобщенного функционального компонента, в виде функционального выражение, возможен путем аннотирования самой функции и переложением ответственности за аннотирование ссылки на вывод типов.
После того, как обобщенный тип был объявлен, его можно начать использовать в .jsx шаблонах.
На этом, беглое рассмотрение объявления и создания обобщенных компонентов закончено, можно переходить к более практическим примерам.
Сложно представить приложение, в котором при построении отображения, обошлось бы без идентичного кода, который повторяется в нескольких частях программы. Поэтому разработчики, на основе готовых, низкоуровневых компонентов, создают свои, более высокоуровневые компоненты. При этом, чтобы их можно было переиспользовать, они должны быть максимально универсальными. Поэтому давайте, на простых примерах, выясним, почему к этому стоит стремится и как этого добится.
Кроме того, бывают случаи, когда массив с данными, по которому строятся компоненты, собирается на основе других данных и сразу же передается в тот компонент, в котором с ним происходит дальнейшая работа. В случаи, когда с этими данными нужно работать после того, как по ним отрендерятся визуальные компоненты, их требуется сохранить в локальное состояние. При повторении данного сценария, это снова приведет к повторению кода и кроме того код программы будет усложнен операциями по сохранению и поддержке данных в актуальном состоянии. Это приводит к нарушению ещё одного принципа известного как принцип KISS (“Keep it simple, stupid”).
Как минимум тип данных, которые ожидает универсальный компонент, должен иметь собственную декларацию и описывать только минимально требующиеся для успешного выполнения характеристики.
В типизированных языках, проблемы с универсальностью, решается с помощью механизма создания обобщенных типов. К тому же TypeScript, поддерживает синтаксис параметризированных компонентов, что будет продемонстрировано в последнем примере.
Очень часто, при разработке React приложений, разработчикам приходится создавать конструкцию, известную в react сообществе, как HOC (Higher-Order Components).
HOC, это функция, которая принимает компонент и возвращает новый компонент. Другими словами, hoc, это функция, ожидающая в качестве параметров компонент (назовем его входным), который оборачивается в другой, объявленный в теле функции, компонент, который выступает в роли возвращаемого из функции значения (назовем его выходным). Слово “оборачивание” применимое относительно компонентов, означает, что один компонент, отрисовывает (рендерит) другой компонент, со всеми вытекающими из этого процесса (проксирование). За счет того, что входной компонент оборачивается в выходной, достигается расширение его и\или общего функционала. Кроме того, это позволяет устанавливать входному компоненту, как зависимости, так и данные, полученные из внешних сервисов.
Если объяснения, что такое hoc и в каких случаях в нем появляется необходимость, выходит за рамки данной книги, то с примерами, иллюстрирующими самые распространенные случаи, для общей картины, ознакомится все же стоит.
Но прежде чем приступить к краткому рассмотрению примеров, будет полезно более подробно ознакомиться с сигнатурой hoc-функции
Как уже было сказано, входной компонент, оборачивается, в объявленный в теле функции, выходной компонент, который может быть как классовым так и функциональным компонентом. И прежде чем кратко ознакомится с каждым из случаев, будет полезно, отдельно рассмотреть сигнатуру hoc-функции на распространенном в практике примере, когда свойства ( props ) выходного компонента, лишь дополняются свойствами входного компонента.
Теперь перейдем к рассмотрению кода, описывающего hoc целиком. Но так как его сигнатура уже была подробно изучена, а в его теле не происходит ничего, что не было бы рассмотрено в этой главе, нет необходимости в каких-либо комментариях.
И начать стоит с hoc, выходной компонент которого является классовым компонентом, использование которого требуется тогда, когда логика зависит от жизненного цикла компонента.
Если же потребности в жизненом цикле нет, то предпочтительней использовать hoc, у которого выходной компонент является функциональным.
И в заключение предлагаю рассмотреть случай, когда параметры устанавливаемые компоненту обертке отличаются от тех, которые он устанавливает оборачиваемому компоненту. И несмотря на то, что код показанный ниже, отличается от предыдущего, подробного разбора не будет, так как в нем нет ничего, что к этому моменту не было бы известно читателю.