Хочешь уверенно проходить IT-интервью?

Мы понимаем, как сложно подготовиться: стресс, алгоритмы, вопросы, от которых голова идёт кругом. Но с AI тренажёром всё гораздо проще.
💡 Почему Т1 тренажёр — это мастхэв?
- Получишь настоящую обратную связь: где затык, что подтянуть и как стать лучше
- Научишься не только решать задачи, но и объяснять своё решение так, чтобы интервьюер сказал: "Вау!".
- Освоишь все этапы собеседования, от вопросов по алгоритмам до диалога о твоих целях.
Зачем листать миллион туториалов? Просто зайди в Т1 тренажёр, потренируйся и уверенно удиви интервьюеров. Мы не обещаем лёгкой прогулки, но обещаем, что будешь готов!
Реклама. ООО «Смарт Гико», ИНН 7743264341. Erid 2VtzqwP8vqy
Зачем использовать TypeScript в React?
React – это JavaScript-библиотека с открытым исходным кодом для создания пользовательских интерфейсов, а TypeScript – типизированное надмножество JavaScript. Объединяя их, мы создаем пользовательские интерфейсы, используя типизированную версию JavaScript. Это означает большую безопасность и меньшее количество ошибок, отправляемых во внешний интерфейс.
Не существует единственного правильного способа написания кода React с использованием TypeScript. Как и в случае с другими технологиями, если ваш код компилируется и работает, вы, вероятно, что-то сделали правильно.
Подготовка компонентов к совместному использованию с помощью TypeScript

Bit.dev стал популярной альтернативой традиционным библиотекам компонентов, поскольку он предлагает способ собрать и поделиться отдельными компонентами из любой кодовой базы.
Создавая проекты с использованием React с TS, вы убедитесь, что ваши компоненты легко понятны другим разработчикам. Это отличный способ написать поддерживаемый код и оптимизировать совместную работу команды.
Настройка проекта и tsconfig.json
Самый быстрый способ запустить приложение React/TypeScript – использовать create-react-app
с шаблоном TypeScript:
npx create-react-app my-app --template typescript
tsconfig.json
это файл конфигурации TypeScript. Файл содержит первоначальные настройки, ниже приведем несколько параметров с пояснениями:
{
"compilerOptions": {
"target": "es5", // Укажите целевую версию ECMAScript
"lib": [
"dom",
"dom.iterable",
"esnext"
], // Список файлов библиотеки для включения в компиляцию
"allowJs": true, // Разрешить компиляцию файлов JavaScript
"skipLibCheck": true, // Пропустить проверку типов всех файлов объявлений
"esModuleInterop": true, // Отключает импорт пространства имен (импорт * как fs из "fs") и включает импорт в стиле CJS / AMD / UMD (импорт fs из "fs")
"allowSyntheticDefaultImports": true, // Разрешить импорт по умолчанию из модулей без экспорта по умолчанию
"strict": true, // Включить все параметры строгой проверки типов
"forceConsistentCasingInFileNames": true, // Запрещаем ссылки с несогласованным регистром на один и тот же файл.
"module": "esnext", // Указываем генерацию кода модуля
"moduleResolution": "node", // Разрешить модули в стиле Node.js
"isolatedModules": true, // Безоговорочно генерировать импорт для неразрешенных файлов
"resolveJsonModule": true, // Включить модули, импортированные с расширением .json
"noEmit": true, // Не выводить вывод (то есть не компилировать код, а только выполнять проверку типа)
"jsx": "react", // Поддержка JSX в файлах .tsx
"sourceMap": true, // Создание соответствующего файла .map
"declaration": true, // Создаем соответствующий файл .d.ts
"noUnusedLocals": true, // Сообщать об ошибках на неиспользуемых локальных объектах
"noUnusedParameters": true, // Сообщаем об ошибках неиспользуемых параметров
"incremental": true, // Включить инкрементную компиляцию путем чтения/записи информации из предыдущих компиляций в файл на диске
"noFallthroughCasesInSwitch": true // Сообщать об ошибках для случаев падения в инструкции switch
},
"include": [
"src/**/*" // *** Файлы TypeScript должны ввести проверку ***
],
"exclude": ["node_modules", "build"] // *** Файлы, которые не нужно вводить, проверять ***
}
Дополнительные рекомендации исходят от сообщества response-typescript-cheatsheet, а объяснения взяты из документации по параметрам компилятора в официальном справочнике TypeScript.
Enums
Enums определяет набор связанных констант как часть единой сущности.
//...
/** A set of groupped constants */
enum SelectableButtonTypes {
Important = "important",
Optional = "optional",
Irrelevant = "irrelevant"
}
interface IButtonProps {
text: string,
/** The type of button, pulled from the Enum SelectableButtonTypes */
type: SelectableButtonTypes,
action: (selected: boolean) => void
}
const ExtendedSelectableButton = ({text, type, action}: IButtonProps) => {
let [selected, setSelected] = useState(false)
return (<button className={"extendedSelectableButton " + type + (selected? " selected" : "")} onClick={ _ => {
setSelected(!selected)
action(selected)
}}>{text}</button>)
}
/** Exporting the component AND the Enum */
export { ExtendedSelectableButton, SelectableButtonTypes}
Использование Enums:
import React from 'react';
import './App.css';
import {ExtendedSelectableButton, SelectableButtonTypes} from './components/ExtendedSelectableButton/ExtendedSelectableButton'
const App = () => {
return (
<div className="App">
<header className="App-header">
<ExtendedSelectableButton type={SelectableButtonTypes.Important} text="Select me!!" action={ (selected) => {
console.log(selected)
}} />
</header>
</div>
);
}
export default App;
Интерфейсы и типы
Что следует использовать – интерфейсы или псевдонимы типов? Хотя эти сущности концептуально различны, на деле они очень похожи:
- обе могут быть продлены;
//расширение интерфейсов
interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }
//расширение типов
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
// Интерфейс расширяет тип
type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }
//Псевдоним типа расширяет интерфейсы
interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };
- обе могут использоваться для определения формы объектов;
//определяем интерфейс для объектов
interface Point {
x: number;
y: number;
}
//также используем типы
type Point2 = {
x: number;
y: number;
};
- обе они могут быть реализованы одинаково;
//реализация интерфейса
class SomePoint implements Point {
x: 1;
y: 2;
}
//Реализация псевдонима типа
class SomePoint2 implements Point2 {
x: 1;
y: 2;
}
type PartialPoint = { x: number; } | { y: number; };
// Единственное, что вы не можете сделать: реализовать тип объединения
class SomePartialPoint implements PartialPoint {
x: 1;
y: 2;
}
Единственная функция интерфейсов, которую не делают псевдонимы типов – это объединение деклараций.
Расширение элементов HTML
Иногда ваши компоненты работают как собственные HTML-элементы. В таких случаях лучше определить тип компонента как собственный элемент HTML или его расширение.
function eventHandler(event: React.MouseEvent<HTMLAnchorElement>) {
console.log("TEST!")
}
const ExtendedSelectableButton = ({text, type, action}: IButtonProps) => {
let [selected, setSelected] = useState(false)
return (<button className={"extendedSelectableButton " + type + (selected? " selected" : "")} onClick={eventHandler}>{text}</button>)
}
Типы событий
React имеет собственный набор событий, поэтому вы не можете напрямую использовать события HTML. Однако у вас есть доступ к событиям пользовательского интерфейса. Убедитесь, что ссылаетесь на них напрямую или просто не забудьте импортировать их из React следующим образом:
import React, { Component, MouseEvent } from 'react';
Мы также можем использовать для ограничения элементов Generics с конкретным обработчиком событий.
Также можно применять объединения, чтобы разрешить повторное использование обработчика несколькими компонентами:
/ ** Это позволит вам использовать этот обработчик событий как для якорей, так и для элементов кнопок * /
function eventHandler(event: React.MouseEvent<HTMLAnchorElement | HTMLButtonElement>) {
console.log("TEST!")
}
Определение интегрированного типа
Стоит упомянуть файлы index.d.ts
и global.d.ts
в React. Оба они устанавливаются, когда вы добавляете React в свой проект. Эти файлы содержат определения типов и интерфейсов: чтобы понять свойства или доступность конкретного типа, вы можете открыть эти файлы и просмотреть их содержимое.

Там вы увидете небольшой раздел файла index.d.ts
, показывающий подписи для функции createElement
.
ESLint/Prettier
Чтобы гарантировать, что ваш код соответствует правилам проекта, а стиль согласован, рекомендуется настроить ESLint
и Prettier
:
- Установите необходимые зависимости для разработчиков:
yarn add eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react --dev
- Создайте файл
.eslintrc.js
в корне и добавьте следующее:
module.exports = {
parser: '@typescript-eslint/parser', // Указывает парсер ESLint
extends: [
'plugin:react/recommended', // Использует рекомендуемые правила из @eslint-plugin-react
'plugin:@typescript-eslint/recommended', // Использует рекомендуемые правила из @typescript-eslint/eslint-plugin
],
parserOptions: {
ecmaVersion: 2018, //Позволяет анализировать современные функции ECMAScript
sourceType: 'module', //Разрешает использование импорта
ecmaFeatures: {
jsx: true, // Разрешает анализ JSX
},
},
rules: {
// Место для указания правил ESLint. Может использоваться для перезаписи правил, указанных в расширенных конфигах
// например "@ typescript-eslint / явный-возвращаемый-тип-функции": "выкл.",
},
settings: {
react: {
version: 'detect', // Указывает eslint-plugin-react автоматически определять версию React для использования
},
},
};
- Добавьте зависимости Prettier:
yarn add prettier eslint-config-prettier eslint-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', // Задает парсер ESLint
extends: [
'plugin:react/recommended', // Использует рекомендуемые правила из @ eslint-plugin-react
'plugin:@typescript-eslint/recommended', // Использует рекомендуемые правила из @typescript-eslint/eslint-plugin
+ 'prettier/@typescript-eslint', // Использует eslint-config-prettier для отключения правил ESLint из @typescript-eslint/eslint-plugin, которые будут конфликтовать с prettier
+ 'plugin:prettier/recommended', // Включает eslint-plugin-prettier и отображает более красивые ошибки как ошибки ESLint. Убедитесь, что это всегда последняя конфигурация в массиве extends.
],
parserOptions: {
ecmaVersion: 2018, // Позволяет анализировать современные функции ECMAScript
sourceType: 'module', // Разрешает использование импорта
ecmaFeatures: {
jsx: true, //Разрешает анализ JSX
},
},
rules: {
// Место для указания правил ESLint. Может использоваться для перезаписи правил, указанных в расширенных конфигах
// например "@typescript-eslint/явный-тип-возврата-функции": "выкл.",
},
settings: {
react: {
version: 'detect', // Указывает eslint-plugin-react автоматически определять версию React для использования
},
},
};
Расширения и настройки кода VS
Следующий шаг по улучшению – автоматическое исправление и предварительная настройка кода при сохранении.
Установите ESLint и Prettier для VS Code. Это позволит ESLint легко интегрироваться с вашим редактором.
Затем обновите настройки, добавив следующий код в свой .vscode/settings.json
:
{
"editor.formatOnSave": true
}
Хуки
Хуки, вроде useState
, получают параметр и правильно возвращают состояние и функцию для его установки.
Вы можете принудительно установить тип или интерфейс начального значения состояния, например, так:
const [user, setUser] = React.useState<IUser>(user);
Однако, если начальное значение для вашего хука потенциально может быть null, то приведенный выше код не сработает. Для этих случаев TypeScript позволяет установить дополнительный тип:
const [user, setUser] = React.useState<IUser | null>(null);
// later...
setUser(newUser);
Обработка событий формы
Один из наиболее распространенных случаев – это правильный ввод using
в поле ввода 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<HTMLInputElement>) {
setValue(e.target.value)
}
return <input value={value} onChange={onChange} id="input-example"/>
}
Расширение свойств компонентов
Можно расширить свойства, объявленные для одного компонента, и задействовать их в другом. Давайте сначала посмотрим, как использовать 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<ContainerProps> = ({ color, height, width, text }) => {
return <div style={{ backgroundColor: color, height: `${height}px` }}>{text}</div>
}
Если вы использовали 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<ContainerProps> = ({ color, height, width, text }) => {
return <div style={{ backgroundColor: color, height: `${height}px` }}>{text}</div>
}
Сторонние библиотеки
Мы часто включаем сторонние библиотеки в проекты React и TypeScript. В таких случаях стоит посмотреть, есть ли пакет @types
с определениями типов:
#yarn
yarn add @types/<package-name>
#npm
npm install @types/<package-name>
Пространство имен @types
зарезервировано для определений типов пакетов. Они живут в репозитории под названием DefinitherTyped
, который частично поддерживается командой TypeScript, а частично – сообществом.
Итоги
Совместное использование React и TypeScript требует некоторого обучения из-за объема информации, но в долгосрочной перспективе затраты времени окупаются. В своей публикации мы опирались на лучшие практики из статей Джо Превайта, Фернандо Дольо и Мартина Хохеля. Мы постарались осветить самые полезные приемы и моменты, которые помогут использовать TypeScript как часть инструментальной цепочки React. Больше информации вы найдете в официальном справочнике к TypeScript или в публикациях «Библиотеки программиста».
Комментарии