Использование TypeScript
TypeScript — это популярный способ добавления определений типов в кодовые базы JavaScript. Из коробки TypeScriptподдерживает JSX, а полную поддержку React Web можно получить, добавив в проект@types/react и @types/react-dom.
Установка
Всеготовые к продакшену фреймворки Reactподдерживают использование TypeScript. Следуйте руководству по установке для конкретного фреймворка:
Добавление TypeScript в существующий проект React
Чтобы установить последнюю версию определений типов для React:
npm install --save-dev @types/react @types/react-domВ вашем файле tsconfig.jsonнеобходимо установить следующие опции компилятора:
domдолжен быть включён вlib(Примечание: если опцияlibне указана,domвключается по умолчанию).- jsxдолжен быть установлен в одно из допустимых значений. Для большинства приложений должно хватить значения
preserveЕсли вы публикуете библиотеку, обратитесь кдокументации по jsx, чтобы выбрать подходящее значение.
TypeScript с компонентами React
Примечание
Каждый файл, содержащий JSX, должен использовать расширение.tsx. Это специфичное для TypeScript расширение, которое сообщает TypeScript, что данный файл содержит JSX.
Написание TypeScript с React очень похоже на написание JavaScript с React. Ключевое отличие при работе с компонентом заключается в том, что вы можете предоставить типы для пропсов вашего компонента. Эти типы можно использовать для проверки корректности и предоставления встроенной документации в редакторах.
Взявкомпонент MyButtonиз руководстваБыстрый старт, мы можем добавить тип, описывающийtitleдля кнопки:
Примечание
Эти песочницы могут обрабатывать код TypeScript, но они не запускают проверку типов. Это означает, что вы можете изменять TypeScript-песочницы для обучения, но не будете получать никаких ошибок или предупреждений типов. Для проверки типов вы можете использоватьTypeScript Playgroundили более полнофункциональную онлайн-песочницу.
Этот встроенный синтаксис — самый простой способ предоставить типы для компонента, однако, когда полей для описания становится несколько, он может стать громоздким. Вместо этого вы можете использоватьinterfaceилиtypeдля описания пропсов компонента:
Тип, описывающий пропсы вашего компонента, может быть как простым, так и сложным, но он должен быть объектным типом, описанным с помощьюtypeилиinterface. Вы можете узнать о том, как TypeScript описывает объекты, в разделеТипы объектов, но вам также может быть интересно использоватьОбъединённые типыдля описания пропса, который может быть одним из нескольких различных типов, а также руководствоСоздание типов из типовдля более сложных случаев использования.
Примеры хуков
Определения типов из@types/reactвключают типы для встроенных хуков, поэтому вы можете использовать их в своих компонентах без дополнительной настройки. Они созданы с учётом кода, который вы пишете в своём компоненте, поэтому вы будете получатьвыводимые типыв большинстве случаев и, в идеале, вам не придётся вникать в детали предоставления типов.
Тем не менее, мы можем рассмотреть несколько примеров того, как предоставлять типы для хуков.
useState
ХукuseStateповторно использует значение, переданное в качестве начального состояния, чтобы определить, каким должен быть тип значения. Например:
Это присвоит переменнойenabledтипboolean, аsetEnabledбудет функцией, принимающей либо аргумент типаboolean, либо функцию, возвращающуюboolean. Если вы хотите явно указать тип для состояния, вы можете сделать это, предоставив аргумент типа при вызовеuseState:
В данном случае это не очень полезно, но распространённый случай, когда вы можете захотеть предоставить тип, — это когда у вас есть объединённый тип. Например,statusздесь может быть одной из нескольких различных строк:
Или, как рекомендуется в разделеПринципы структурирования состояния, вы можете сгруппировать связанное состояние в объект и описать различные возможности с помощью объектных типов:
useReducer
ХукuseReducer— это более сложный хук, который принимает функцию-редьюсер и начальное состояние. Типы для функции-редьюсера выводятся из начального состояния. Вы можете дополнительно предоставить аргумент типа при вызовеuseReducer, чтобы указать тип для состояния, но часто лучше установить тип на начальном состоянии:
Мы используем TypeScript в нескольких ключевых местах:
interface Stateописывает структуру состояния редюсера.type CounterActionописывает различные действия, которые могут быть отправлены в редюсер.const initialState: Stateпредоставляет тип для начального состояния, а также тип, который по умолчанию используется вuseReducer.stateReducer(state: State, action: CounterAction): Stateзадаёт типы для аргументов функции редюсера и возвращаемого значения.
Более явной альтернативой заданию типа дляinitialStateявляется передача аргумента типа вuseReducer:
useContext
ХукuseContext— это техника передачи данных вниз по дереву компонентов без необходимости прокидывать пропсы через компоненты. Она используется путём создания компонента-провайдера и часто создания хука для потребления значения в дочернем компоненте.
Тип значения, предоставляемого контекстом, выводится из значения, переданного в вызовcreateContext:
Эта техника работает, когда у вас есть осмысленное значение по умолчанию, но иногда возникают случаи, когда его нет, и в таких случаяхnullможет казаться разумным значением по умолчанию. Однако, чтобы система типов могла понять ваш код, вам нужно явно указатьContextShape | null в createContext.
Это приводит к проблеме, что вам нужно исключить| nullв типе для потребителей контекста. Наша рекомендация — поручить хуку выполнить проверку во время выполнения на его существование и выбросить ошибку, если его нет:
useMemo
Примечание
React Compilerавтоматически мемоизирует значения и функции, уменьшая необходимость в ручных вызовахuseMemo. Вы можете использовать компилятор для автоматической обработки мемоизации.
ХукuseMemoсоздаёт/повторно получает мемоизированное значение из вызова функции, повторно запуская функцию только тогда, когда изменяются зависимости, переданные в качестве второго параметра. Результат вызова хука выводится из возвращаемого значения функции в первом параметре. Вы можете быть более явными, предоставив аргумент типа для хука.
useCallback
Примечание
React Compilerавтоматически мемоизирует значения и функции, уменьшая необходимость в ручных вызовахuseCallback. Вы можете использовать компилятор для автоматической обработки мемоизации.
ХукuseCallbackпредоставляет стабильную ссылку на функцию до тех пор, пока зависимости, переданные во второй параметр, остаются неизменными. Как и в случае сuseMemo, тип функции выводится из возвращаемого значения функции в первом параметре, и вы можете быть более явными, предоставив аргумент типа для хука.
При работе в строгом режиме TypeScriptuseCallbackтребует добавления типов для параметров в вашем колбэке. Это связано с тем, что тип колбэка выводится из возвращаемого значения функции, и без параметров тип не может быть полностью понят.
В зависимости от ваших предпочтений по стилю кода, вы можете использовать функции*EventHandlerиз типов React, чтобы предоставить тип для обработчика события одновременно с определением колбэка:
Полезные типы
Пакет @types/reactсодержит довольно обширный набор типов, с которым стоит ознакомиться, когда вы почувствуете себя уверенно во взаимодействии React и TypeScript. Вы можете найти ихв папке React в DefinitelyTyped. Здесь мы рассмотрим несколько наиболее распространённых типов.
События DOM
При работе с событиями DOM в React тип события часто может быть выведен из обработчика события. Однако, когда вы хотите вынести функцию для передачи в обработчик события, вам нужно будет явно указать тип события.
В типах React предоставлено множество типов событий — полный список можно найтиздесь, он основан нанаиболее популярных событиях DOM.
Чтобы определить нужный вам тип, вы можете сначала посмотреть на информацию при наведении на используемый обработчик события, которая покажет тип события.
Если вам нужно использовать событие, не включённое в этот список, вы можете использовать типReact.SyntheticEvent, который является базовым типом для всех событий.
Дочерние элементы (Children)
Есть два распространённых способа описания дочерних элементов компонента. Первый — использовать типReact.ReactNode, который представляет собой объединение всех возможных типов, которые могут быть переданы как дочерние элементы в JSX:
Это очень широкое определение дочерних элементов. Второй способ — использовать типReact.ReactElement, который включает только JSX-элементы, а не примитивы JavaScript, такие как строки или числа:
Обратите внимание, что вы не можете использовать TypeScript для описания того, что дочерние элементы являются определённым типом JSX-элементов, поэтому вы не можете использовать систему типов для описания компонента, который принимает только дочерние элементы типа<li>.
Вы можете увидеть примеры использования какReact.ReactNode, так иReact.ReactElementс проверкой типов вэтой песочнице TypeScript.
Свойства стилей (Style Props)
При использовании встроенных стилей в React вы можете использоватьReact.CSSPropertiesдля описания объекта, передаваемого в пропсstyle. Этот тип представляет собой объединение всех возможных CSS-свойств и является хорошим способом убедиться, что вы передаёте допустимые CSS-свойства в пропсstyle, а также получить автодополнение в вашем редакторе.
Дальнейшее изучение
На отдельных страницах документации по API может содержаться более подробная информация о том, как использовать их с TypeScript.
Мы рекомендуем следующие ресурсы:
- Справочник по TypeScript— это официальная документация по TypeScript, охватывающая большинство ключевых возможностей языка.
- Примечания к выпускам TypeScriptподробно описывают новые функции.
- Шпаргалка по React TypeScript— это поддерживаемая сообществом шпаргалка по использованию TypeScript с React, охватывающая множество полезных крайних случаев и предоставляющая более широкий охват, чем этот документ.
- Сообщество TypeScript в Discord— отличное место, чтобы задавать вопросы и получать помощь по вопросам, связанным с TypeScript и React.
