Изготовление сайтов в Мариуполе, ДНР. Реагируйте с помощью TypeScript: лучшие практики

 
 

React и TypeScript — две замечательные технологии, используемые сегодня многими разработчиками. Знание того, как что-то делать, может быть сложным, и иногда трудно найти правильный ответ. Не беспокоиться. Мы собрали лучшие практики вместе с примерами, чтобы прояснить любые сомнения, которые могут у вас возникнуть.

Давайте погрузимся!

Как React и TypeScript работают вместе

Прежде чем мы начнем, давайте еще раз посмотрим, как React и TypeScript работают вместе. React — это «библиотека JavaScript для создания пользовательских интерфейсов», а TypeScript — «типизированный надмножество JavaScript, который компилируется в простой JavaScript». Используя их вместе, мы, по сути, создаем наши пользовательские интерфейсы, используя типизированную версию JavaScript.

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

Компилирует ли TypeScript мой код React?

Распространенный вопрос, на который всегда полезно ответить, — компилирует ли TypeScript ваш код React. Принцип работы TypeScript аналогичен этому взаимодействию:

ТС: «Эй, это весь код твоего пользовательского интерфейса?»

Реакция: «Ага!»

ТС: «Круто! Я собираюсь скомпилировать его и убедиться, что вы ничего не пропустили».

Реакция: «Звучит хорошо для меня!»

Так что ответ — да, это так! Но позже, когда мы рассмотрим tsconfig.jsonнастройки, большую часть времени вы захотите использовать файлы «noEmit»: true. Это означает, что TypeScript не будет выдавать JavaScript после компиляции. Это потому, что обычно мы используем TypeScript только для проверки типов.

Вывод обрабатывается в настройках CRA с помощью react-scripts. Мы запускаем yarn buildи react-scriptsобъединяем результаты для производства.

Напомним, что TypeScript компилирует ваш код React для проверки кода. Он не выдает никакого вывода JavaScript (в большинстве сценариев). Вывод по-прежнему похож на проект React без TypeScript.

Может ли TypeScript работать с React и webpack?

Да, TypeScript может работать с React и webpack. К счастью для вас, в документации по веб-пакету есть руководство по этому вопросу.

Надеюсь, это даст вам небольшое освежение в том, как они работают вместе. Теперь о лучших практиках!

Лучшие практики

Мы изучили наиболее распространенные вопросы и составили этот удобный список наиболее распространенных вариантов использования React с TypeScript. Таким образом, вы можете использовать эту статью в качестве справочника в своих собственных проектах.

Конфигурация

Одна из наименее увлекательных, но наиболее важных частей разработки — конфигурация. Как мы можем настроить вещи в кратчайшие сроки, чтобы обеспечить максимальную эффективность и производительность? Мы обсудим настройку проекта, включая:

tsconfig.json

ESLint

красивее

Расширения и настройки VS Code.

Настройка проекта

Самый быстрый способ запустить приложение React/TypeScript — использовать create-react-appшаблон TypeScript. Вы можете сделать это, запустив:

npx create-react-appmy-app —template typescript

Это даст вам необходимый минимум, чтобы начать писать React с помощью TypeScript. Несколько заметных отличий:

расширение.tsxфайла

вtsconfig.json

вreact-app-env.d.ts

Это tsxдля «TypeScript JSX». Это tsconfig.jsonфайл конфигурации TypeScript, в котором установлены некоторые значения по умолчанию. Ссылается react-app-env.d.tsна типы react-scriptsи помогает с такими вещами, как разрешение импорта SVG.

tsconfig.json

К счастью для нас, для нас генерируется последний шаблон React/TypeScript tsconfig.json. Тем не менее, они добавляют необходимый минимум для начала работы. Мы предлагаем вам изменить свой, чтобы он соответствовал приведенному ниже. Мы также добавили комментарии, объясняющие назначение каждой опции:

{

«compilerOptions»: {

«target»: «es5», // Specify ECMAScript target version

«lib»: [

«dom»,

«dom.iterable»,

«esnext»

], // List of library files to be included in the compilation

«allowJs»: true, // Allow JavaScript files to be compiled

«skipLibCheck»: true, // Skip type checking of all declaration files

«esModuleInterop»: true, // Disables namespace imports (import * as fs from «fs») and enables CJS/AMD/UMD style imports (import fs from «fs»)

«allowSyntheticDefaultImports»: true, // Allow default imports from modules with no default export

«strict»: true, // Enable all strict type checking options

«forceConsistentCasingInFileNames»: true, // Disallow inconsistently-cased references to the same file.

«module»: «esnext», // Specify module code generation

«moduleResolution»: «node», // Resolve modules using Node.js style

«isolatedModules»: true, // Unconditionally emit imports for unresolved files

«resolveJsonModule»: true, // Include modules imported with.json extension

«noEmit»: true, // Do not emit output (meaning do not compile code, only perform type checking)

«jsx»: «react», // Support JSX in.tsx files

«sourceMap»: true, // Generate corrresponding.map file

«declaration»: true, // Generate corresponding.d.ts file

«noUnusedLocals»: true, // Report errors on unused locals

«noUnusedParameters»: true, // Report errors on unused parameters

«incremental»: true, // Enable incremental compilation by reading/writing information from prior compilations to a file on disk

«noFallthroughCasesInSwitch»: true // Report errors for fallthrough cases in switch statement

},

«include»: [

«src/**/*» // *** The files TypeScript should type check ***

],

«exclude»: [«node_modules», «build»] // *** The files to not type check ***

}

Дополнительные рекомендации исходят от сообщества react-typescript-cheatsheet, а пояснения — из документации по параметрам компилятора в официальном руководстве по TypeScript. Это замечательный ресурс, если вы хотите узнать о других вариантах и ​​о том, что они делают.

ESLint/красивее

Чтобы убедиться, что ваш код соответствует правилам проекта или вашей команды, а стиль согласован, рекомендуется настроить ESLint и Prettier. Чтобы заставить их играть хорошо, выполните следующие действия, чтобы настроить его.

Установите необходимые зависимости для разработчиков:

yarn add eslint @typescript-eslint/parser @typescript-eslint/eslint-plugineslint-plugin-react —dev

Создайте.eslintrc.jsфайл в корне и добавьте следующее:

module.exports = {

parser: '@typescript-eslint/parser’, // Specifies the ESLint parser

extends: [

‘plugin: react/recommended’, // Uses the recommended rules from @eslint-plugin-react

‘plugin: @typescript-eslint/recommended’, // Uses the recommended rules from @typescript-eslint/eslint-plugin

],

parserOptions: {

ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features

sourceType: ‘module’, // Allows for the use of imports

ecmaFeatures: {

jsx: true, // Allows for the parsing of JSX

},

},

rules: {

// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs

// e.g. «@typescript-eslint/explicit-function-return-type»: «off»,

},

settings: {

react: {

version: ‘detect’, // Tells eslint-plugin-react to automatically detect the version of React to use

},

},

};

Добавьте зависимости Prettier:

yarn add prettier eslint-config-prettiereslint-plugin-prettier —dev

Создайте.prettierrc.jsфайл в корне и добавьте следующее:

module.exports = {

semi: true,

trailingComma: ‘all’,

singleQuote: true,

printWidth: 120,

tabWidth: 4,

};

Обновите.eslintrc.jsфайл:

module.exports = {

parser: '@typescript-eslint/parser’, // Specifies the ESLint parser

extends: [

‘plugin: react/recommended’, // Uses the recommended rules from @eslint-plugin-react

‘plugin: @typescript-eslint/recommended’, // Uses the recommended rules from the @typescript-eslint/eslint-plugin

+ ‘prettier/@typescript-eslint’, // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier

+ ‘plugin: prettier/recommended’, // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.

],

parserOptions: {

ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features

sourceType: ‘module’, // Allows for the use of imports

ecmaFeatures: {

jsx: true, // Allows for the parsing of JSX

},

},

rules: {

// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs

// e.g. «@typescript-eslint/explicit-function-return-type»: «off»,

},

settings: {

react: {

version: ‘detect’, // Tells eslint-plugin-react to automatically detect the version of React to use

},

},

};

Эти рекомендации взяты из ресурса сообщества, написанного Робертом Купером под названием «Использование ESLint и Prettier в проекте TypeScript «. Если вы посетите этот ресурс, вы сможете узнать больше о том, «почему» стоят за этими правилами и конфигурациями.

Расширения и настройки кода VS

Мы добавили ESLint и Prettier, и следующим шагом по улучшению нашего DX является автоматическое исправление/улучшение нашего кода при сохранении.

Сначала установите расширение ESLint и расширение Prettier для VS Code. Это позволит ESLint легко интегрироваться с вашим редактором.

Затем обновите настройки рабочей области, добавив следующее.vscode/settings.json:

{

«editor.formatOnSave»: true

}

Это позволит VS Code творить чудеса и исправлять ваш код при сохранении. Оно прекрасно!

Эти предложения также взяты из ранее связанной статьи «Использование ESLint и Prettier в проекте TypeScript «Роберта Купера.

Примечание: чтобы узнать больше о React.FC, смотрите здесь и читайте здесь о React.ReactNode.

Компоненты

Одной из основных концепций React являются компоненты. Здесь мы будем ссылаться на стандартные компоненты React v16.8, то есть те, которые используют хуки, а не классы.

В общем, по основным компонентам есть на что обратить внимание. Давайте посмотрим на пример:

import React from ‘react’

// Written as a function declaration

function Heading (): React.ReactNode {

return My Website Heading

}

// Written as a function expression

const OtherHeading: React.FC = () => My Website Heading

Обратите внимание на ключевое отличие здесь. В первом примере мы пишем нашу функцию как объявление функции. Мы аннотируем возвращаемый тип, React.Nodeпотому что это то, что он возвращает. Напротив, во втором примере используется функциональное выражение. Поскольку второй экземпляр возвращает функцию, а не значение или выражение, мы аннотируем тип функции для React.FCReact «Функциональный компонент».

Это может сбивать с толку, чтобы помнить два. В основном это вопрос выбора дизайна. Что бы вы ни выбрали для своего проекта, используйте его последовательно.

Реквизит

Следующее основное понятие, которое мы рассмотрим, — реквизит. Вы можете определить свои реквизиты, используя либо интерфейс, либо тип. Давайте посмотрим на другой пример:

import React from ‘react’

interface Props {

name: string;

color: string;

}

type OtherProps = {

name: string;

color: string;

}

// Notice here we’re using the function declaration with the interface Props

function Heading ({ name, color }: Props): React.ReactNode {

return My Website Heading

}

// Notice here we’re using the function expression with the type OtherProps

const OtherHeading: React.FC = ({ name, color }) =>

My Website Heading

Когда дело доходит до типов или интерфейсов, мы предлагаем следовать рекомендациям, представленным react-typescript-cheatsheetсообществом:

«Всегда используйте интерфейс для общедоступного API-определения при создании библиотеки или сторонних определений внешнего типа».

«рассмотрите возможность использования типа для реквизитов и состояния вашего компонента React, потому что он более ограничен».

Вы можете прочитать больше об обсуждении и увидеть удобную таблицу сравнения типов и интерфейсов здесь.

Давайте посмотрим на еще один пример, чтобы мы могли увидеть что-то более практичное:

import React from ‘react’

type Props = {

/** color to use for the background */

color?: string;

/** standard children prop: accepts any valid React Node */

children: React.ReactNode;

/** callback function passed to the onClick handler*/

onClick: () => void;

}

const Button: React.FC = ({ children, color = ‘tomato’, onClick }) => {

return

}

В этом

 

Всегда добавляйте описательные комментарии к своим свойствам, используя нотацию TSDoc /** comment */.

Независимо от того, используете ли вы типы или интерфейсы для свойств вашего компонента, используйте их последовательно.

Когда props являются необязательными, обрабатывайте их соответствующим образом или используйте значения по умолчанию.

Крючки

К счастью, вывод типа TypeScript хорошо работает при использовании хуков. Это означает, что вам не о чем беспокоиться. Например, возьмем этот пример:

// `value` is inferred as a string

// `setValue` is inferred as (newValue: string) => void

const [value, setValue] = useState ('')

TypeScript выводит значения, данные для использования useStateхуком. Это та область, где React и TypeScript просто работают вместе, и это прекрасно.

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

type User = {

email: string;

id: string;

}

// the generic is the < >

// the union is the User | null

// together, TypeScript knows, «Ah, user can be User or null».

const [user, setUser] = useState (null) ;

Другое место, где TypeScript сияет с помощью хуков, — это userReducer, где вы можете воспользоваться преимуществами размеченных объединений. Вот полезный пример:

type AppState = {};

type Action =

| { type: «SET_ONE»; payload: string }

| { type: «SET_TWO»; payload: number };

export function reducer (state: AppState, action: Action): AppState {

switch (action.type) {

case «SET_ONE»:

return {

...state,

one: action.payload // `payload` is string

};

case «SET_TWO»:

return {

...state,

two: action.payload // `payload` is number

};

default:

return state;

}

}

Источник: react-typescript-cheatsheet раздел крючков

Красота здесь заключается в полезности разрозненных союзов. Обратите внимание Actionна объединение двух похожих друг на друга объектов. Свойство typeявляется строковым литералом. Разница между этим и типом stringзаключается в том, что значение должно соответствовать литеральной строке, определенной в типе. Это означает, что ваша программа более безопасна, поскольку разработчик может вызвать только действие, для которого установлен typeключ «SET_ONE»или «SET_TWO».

Как видите, хуки не усложняют природу проекта React и TypeScript. Во всяком случае, они хорошо подходят для дуэта.

Общие случаи использования

Этот раздел посвящен наиболее распространенным случаям использования, когда люди спотыкаются при использовании TypeScript с React. Мы надеемся, что, поделившись этим, вы избежите ловушек и даже поделитесь этими знаниями с другими.

Обработка событий формы

Одним из наиболее распространенных случаев является правильный ввод onChangeиспользуемого в поле ввода в форме. Вот пример:

import React from ‘react’

const MyInput = () => {

const [value, setValue] = React.useState ('')

// The event type is a «ChangeEvent»

// We pass in «HTMLInputElement» to the input

function onChange (e: React.ChangeEvent) {

setValue (e.target.value)

}

return

}

Расширение свойств компонента

Иногда вы хотите взять реквизиты компонента, объявленные для одного компонента, и расширить их, чтобы использовать их в другом компоненте. Но вы можете изменить один или два. Ну, помните, как мы рассматривали два способа ввода реквизитов компонентов, типов и интерфейсов? В зависимости от того, что вы использовали, определяется, как вы расширяете свойства компонента. Давайте сначала посмотрим на способ использования type:

import React from ‘react’;

type ButtonProps = {

/** the background color of the button */

color: string;

/** the text to show inside the button */

text: string;

}

type ContainerProps = ButtonProps & {

/** the height of the container (value used with ‘px’) */

height: number;

}

const Container: React.FC = ({ color, height, width, text }) => {

return <div style={{ backgroundColor: color, height: `${height}px` }}>{text}

}

Если вы объявили свои реквизиты с помощью interface, то мы можем использовать ключевое слово extends, чтобы существенно «расширить» этот интерфейс, но внести пару модификаций:

import React from ‘react’;

interface ButtonProps {

/** the background color of the button */

color: string;

/** the text to show inside the button */

text: string;

}

interface ContainerProps extends ButtonProps {

/** the height of the container (value used with ‘px’) */

height: number;

}

const Container: React.FC = ({ color, height, width, text }) => {

return <div style={{ backgroundColor: color, height: `${height}px` }}>{text}

}

Оба метода решают проблему. Вам решать, что использовать. Лично мне расширение интерфейса кажется более читабельным, но в конечном счете это зависит от вас и вашей команды.

Вы можете прочитать больше об обеих концепциях в Справочнике по TypeScript:

Типы пересечений

Расширение интерфейсов

Сторонние библиотеки

Будь то для клиента GraphQL, такого как Apollo, или для тестирования с чем-то вроде React Testing Library, мы часто используем сторонние библиотеки в проектах React и TypeScript. Когда это происходит, первое, что вы хотите сделать, это посмотреть, есть ли @typesпакет с определениями типов TypeScript. Вы можете сделать это, запустив:

#yarn

yarn add @types/<package-name>

#npm

npm install @types/<package-name>

Например, если вы используете Jest, вы можете сделать это, запустив:

#yarn

yarn add @types/jest

#npm

npm install @types/jest

Это даст вам дополнительную безопасность типов всякий раз, когда вы используете Jest в своем проекте.

Пространство @typesимен зарезервировано для определений типов пакетов. Они живут в репозитории под названием DefinitelyTyped, который частично поддерживается командой TypeScript и частично сообществом.

Должны ли они быть сохранены как dependenciesили devDependenciesв моем package.json?

Короткий ответ: «это зависит». В большинстве случаев они могут выйти devDependenciesиз строя, если вы создаете веб-приложение. Однако, если вы пишете библиотеку React на TypeScript, вы можете включить их как файлы dependencies.

На Stack Overflow есть несколько ответов на этот вопрос, которые вы можете проверить для получения дополнительной информации.

Что произойдет, если у них нет пакета @types?

Если вы не найдете @typesпакет в npm, у вас есть два варианта:

Добавьте базовый файл объявления

Добавить подробный файл декларации

Первый вариант означает, что вы создаете файл на основе имени пакета и кладете его в корень. Если, например, нам нужны типы для нашего пакета banana-js, то мы могли бы создать базовый файл объявления, вызываемый banana-js.d.tsв корне:

declare module ‘banana-js’;

Это не обеспечит вам безопасность типов, но разблокирует вас.

Более подробный файл объявления будет там, где вы добавляете типы для библиотеки/пакета:

declare namespace bananaJs {

function getBanana (): string;

function addBanana (n: number) void;

function removeBanana (n: number) void;

}

Если вы никогда не писали файл объявления, то предлагаем вам взглянуть на руководство в официальном TypeScript Handbook.

Резюме

Лучшее совместное использование React и TypeScript требует некоторого обучения из-за большого количества информации, но в долгосрочной перспективе преимущества окупаются. В этой статье мы рассмотрели конфигурацию, компоненты, реквизиты, хуки, распространенные варианты использования и сторонние библиотеки. Хотя мы могли бы углубиться во многие отдельные области, это должно охватывать 80%, необходимые для того, чтобы помочь вам следовать рекомендациям.

3D-печать5GABC-анализAndroidAppleAppStoreAsusCall-центрChatGPTCRMDellDNSDrupalExcelFacebookFMCGGoogleHuaweiInstagramiPhoneLinkedInLinuxMagentoMicrosoftNvidiaOpenCartPlayStationPOS материалPPC-специалистRuTubeSamsungSEO-услугиSMMSnapchatSonyStarlinkTikTokTwitterUbuntuUp-saleViasatVPNWhatsAppWindowsWordPressXiaomiYouTubeZoomАвдеевкаАктивные продажиАкцияАлександровск ЛНРАлмазнаяАлчевскАмвросиевкаАнализ конкурентовАнализ продажАнтимерчандайзингАнтрацитАртемовскАртемовск ЛНРАссортиментная политикаБелгородБелицкоеБелозерскоеБердянскБизнес-идеи (стартапы)БрендБрянкаБукингВахрушевоВендорВидеоВикипедияВирусная рекламаВирусный маркетингВладивостокВнутренние продажиВнутренний маркетингВолгоградВолновахаВоронежГорловкаГорнякГорскоеДебальцевоДебиторкаДебиторская задолженностьДезинтермедитацияДзержинскДивизионная система управленияДизайнДимитровДирект-маркетингДисконтДистрибьюторДистрибьюцияДобропольеДокучаевскДоменДружковкаЕкатеринбургЕнакиевоЖдановкаЗапорожьеЗимогорьеЗолотоеЗоринскЗугрэсИжевскИловайскИрминоКазаньКалининградКировскКировскоеКомсомольскоеКонстантиновкаКонтент-маркетингКонтент-планКопирайтингКраматорскКрасноармейскКрасногоровкаКраснодарКраснодонКраснопартизанскКрасный ЛиманКрасный ЛучКременнаяКураховоКурскЛисичанскЛуганскЛутугиноМакеевкаМариупольМаркетингМаркетинговая информацияМаркетинговые исследованияМаркетинговый каналМаркетинг услугМаркетологМарьинкаМедиаМелекиноМелитопольМенеджментМерчандайзерМерчандайзингМиусинскМолодогвардейскМоскваМоспиноНижний НовгородНиколаевНиколаевкаНишевой маркетингНовоазовскНовогродовкаНоводружескНовосибирскНумерическая дистрибьюцияОдессаОмскОтдел маркетингаПартизанский маркетингПервомайскПеревальскПетровскоеПлата за кликПоисковая оптимизацияПопаснаяПравило ПаретоПривольеПрогнозирование продажПродвижение сайтов в ДонецкеПроизводство видеоПромоПромоушнПрямой маркетингРабота для маркетологаРабота для студентаРазработка приложенийРаспродажаРегиональные продажиРекламаРеклама на асфальтеРемаркетингРетро-бонусРибейтРитейлРовенькиРодинскоеРостов-на-ДонуРубежноеСамараСанкт-ПетербургСаратовСватовоСвердловскСветлодарскСвятогорскСевастопольСеверодонецкСеверскСедовоСейлз промоушнСелидовоСимферопольСинергияСколковоСлавянскСнежноеСоздание сайтов в ДонецкеСоледарСоциальные сетиСочиСтаробельскСтаробешевоСтахановСтимулирование сбытаСуходольскСчастьеТелемаркетингТельмановоТираспольТорговый представительТорезТрейд маркетингТрейд промоушнТюменьУглегорскУгледарУкраинскХабаровскХарцызскХерсонХостингЦелевая аудиторияЦифровой маркетингЧасов ЯрЧелябинскШахтерскЮжно-СахалинскЮнокоммунаровскЯндексЯсиноватая