🙋🏻‍♀️Введение

⚛️Как использовать TypeScript с React?

🪞Типы свойств компонента React

🛑ReactNode против ReactElement

🏷Тип и интерфейс

🪢Как печатать реквизиты с помощью TypeScript?

🪡Как вводить реквизит функционального компонента?

React Hooks с помощью TypeScript

Введение

React — это популярная библиотека JavaScript для создания пользовательских интерфейсов. Он известен своей простотой, производительностью и гибкостью. Однако JavaScript — это язык с динамической типизацией, а это означает, что во время выполнения могут возникать ошибки. Здесь на помощь приходит TypeScript.

TypeScript добавляет в JavaScript статическую типизацию, что помогает обнаруживать ошибки до их возникновения. То есть TypeScript проверяет время компиляции. Это может улучшить качество и ремонтопригодность приложений React. Вот краткий обзор его использования.

Для компиляции кода TypeScript ищет tsconfig.json в корневой папке для инструкций. Он загружает и использует настроенные параметры для сборки приложения.

Как использовать TypeScript с React?

  • Чтобы добавить TypeScript в существующий проект, сначала установите его:

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

or

yarn add typescript @types/node @types/react @types/react-dom @types/jest

  • Создайте файл tsconfig.json вручную или с помощью команды терминала, а затем заполните его моим примером файла.

tsc --init

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noImplicitAny": false,
    "noEmit": true,
    "jsx": "react-jsx",
    "baseUrl": "./src/"
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
  • Затем переименуйте любой файл в файл TypeScript (например, src/index.js в src/index.tsx) и перезапустите сервер разработки!
  • Если для флага allowJs в файле tsconfig.js установлено значение true, это также позволит использовать файлы .js. По умолчанию TypeScript поддерживает только .ts файлов.
  • В проектах React с Vite в качестве сборщика .tsx файлов поддерживаются по умолчанию. Принимая во внимание, что в других сборщиках, таких как webpack, вам необходимо настроить его, чтобы включить использование расширения .tsx. Например,

Для дальнейшей настройки измените расширение файла на .ts или .tsx в соответствии с требованиями.

  • Используйте .ts при переименовании, когда вы создаете функции, классы, редукторы и т. д., которые не требуют использования синтаксиса и элементов JSX, тогда как расширение файла .tsx используется при создании компонента React и использовании элементов и синтаксиса JSX.
  • Ошибки типа будут отображаться в той же консоли, что и ошибка сборки. Вам придется исправить эти ошибки типа, прежде чем продолжить разработку или построить свой проект.

Типы реквизитов компонента React

Реквизиты могут в основном иметь примитивные типы данных, такие как string, number и boolean.

type Person = {
  // primitive types
  name: string,
  age: number,
  isUser: boolean
}

Чтобы создать array одного типа, используйте обозначение литерала массива ([]) после типа.

type Person = {
  name: string[], // an array of string
  age: number,
  isUser: boolean
}

Чтобы получить точное соответствие значения реквизита, используйте литералы. React выдаст ошибку, если значение свойства не соответствует определенному значению literal.

type Props = {
  type: "old" | "new" | "latest",
  part: 1 | 2 | 3
}

Чтобы ввести реквизит object,

type Props = {
  person: {
    name: string,
    age: number,
    isUser: boolean
  }
}

Чтобы ввести children prop, мы можем использовать ReactNode.

React.PropsWithChildrentype берет вашу компонентную поддержку и возвращает тип объединения с соответствующим типом childrenprop.

type PropsWithChildren<P> = P & { children?: ReactNode };

Чтобы ввести компонент React function, в TypeScript есть React.FunctionComponent или React.FC, чтобы использовать его более короткую версию.

type Person = {
  name : string
}
const App:React.FC<Person> = ({name}) => {
  return (
      <h1>{name}</h1>
  )
}

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

Вводить элементы формы с помощью TypeScript довольно просто.

Функция handleChange принимает событие типа React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, что означает, что она может обрабатывать события как от элементов input, так и от элементов textarea.

ReactNode против ReactElement

Реагировать на элемент

Элемент React – это описание компонента, который можно отобразить на экране. Это простой объект JavaScript, представляющий элемент DOM или компонент.

Элементы React создаются с использованием синтаксиса JSX, который представляет собой расширение синтаксиса для JavaScript, которое позволяет вам писать HTML-подобный код в ваших файлах JavaScript. Например, следующий код JSX создает элемент React, представляющий заголовок:

const heading = <h1>Hello, World!</h1>;

Реагировать узел

С другой стороны, узел React — это более общий термин, который относится к любому объекту, который может быть отображен в модели React DOM.

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

const message = "Hello, World!";
const node = <div>{message}</div>;

Тип против интерфейса

Тип

type определяет структуру объектов или сложных типов данных, которые мы используем в нашем коде.

TypeScript имеет тип данных any, который представляет собой надмножество всех типов. Кроме того, он имеет типы данных built-in и user-defined.

Интерфейс

В TypeScript interface дает подробную информацию о форме объекта. Компилятор TypeScript может использовать их для предоставления информации об именах свойств объектов и типах данных, которые могут содержать их значения.

Случай использования псевдонимов типов по сравнению с интерфейсом:

type и interface работают одинаково хорошо.

Если вы хотите добавить некоторые свойства/методы/события после определения стандартной структуры, предпочтительнее использовать interface. Использование type для этого выдает ошибку; как только это будет определено. type нельзя изменить вне его определения. Слияние объявлений не будет работать в type. С другой стороны, interface является расширяемым (объединяемым).

С помощью type и interface вы можете расширить некоторые функции/свойства/методы существующей структуры. interface предпочтительнее, так как это упрощает и делает более управляемым.

type наиболее широко используется, если вам не нужна особая функция interface для публичного показа. Кроме того, type также используется для создания кортежей, объединений и пересечений. Кроме того, interface отлично работает с классами. interface может продолжать type, а type может пересекаться с interface, если только не возникнут следующие сценарии:

Интерфейс не может расширять что-то, если он не знает входящий тип. Если вы сильно полагаетесь на «union» для большей части своего кода, тогда лучше используйте тип, а не интерфейс.

Вы также можете создавать псевдонимы типов и реализовывать их с классом. Класс не может реализовать тип объединения.

Как печатать реквизит с помощью TypeScript?

Props в React используются для хранения и передачи данных от родительского компонента к дочернему компоненту. Реквизиты играют жизненно важную роль, когда дело доходит до создания реальных приложений. Давайте посмотрим, как вводить некоторые реквизиты.

Его синтаксис довольно прост. Вам нужно добавить: и нотацию литерала объекта {} рядом с назначением деструктурирования реквизита children в объявлении компонента. Кроме того, вы можете создать псевдоним Type для реквизита. Вы даже можете сделать реквизит optional, добавив ? после имени реквизита.

const app = ({ title }:{ title : string }) => (
  <h1>{title}</h1>
)

Ввод реквизитов события:

У нас есть различные категории событий. Давайте возьмем пример ввода события клика в качестве реквизита компонента. Реквизиты React также могут принимать такие функции, как onClick и onChange, поэтому вам может потребоваться ввести реквизиты функций. Компонент button принимает событие click в качестве реквизита и передает его элементу HTML Button.

Ввод реквизитов функционального компонента:

В TypeScript есть React.FunctionComponent, или вы можете сказать React.FC, чтобы ввести React Function Components.

Этот подход используется для доступа к дополнительному набору свойств, таких как propTypes, defaultProps, contextTypes и т. д., а также позволяет TypeScript узнать, что это компонент React.

Крючки для набора текста

Хуки поддерживаются в [@types/react начиная с версии 16.8](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a05cc538a42243c632f054e42eab483ebf1560ab/types/react/index.d.ts#L800-L1031). На самом деле не нужно набирать хук каждый раз. В большинстве случаев об этом позаботится вывод типа для простых значений.

хук useState

Однако, чтобы типизировать хуки, явно определите тип и используйте тип объединения:

const [person, setPerson] = useState<Person | null>(null);
//to use later
setPerson(newPerson);

Вы также можете использовать утверждения типов, если состояние инициализируется вскоре после установки и всегда имеет значение после:

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

const [person, setPerson] = useState<Person>({} as Person);
// to use later
setPerson(newPerson);

перехватчик useCallback

Печатать useCallbacks весело. Вы можете ввести хук useCallback точно так же, как вы вводите функции.

const myCallback = useCallback(
  (name: string, age: number) => {
    console.log(name, age)
    return { status: true }
  },
  [...],
);

Обратите внимание, что сигнатура функции может различаться в зависимости от версии React.

хук useReducer

Размеченные союзы прекрасно сочетаются с редьюсерами. Кроме того, они определяют тип возвращаемого значения, если вы его не укажете.

import { useReducer } from "react";
const initialState = { count: 0 };
type ACTIONTYPE =
  | { type: "increment"; payload: number }
  | { type: "decrement"; payload: string };
function reducer(state: typeof initialState, action: ACTIONTYPE) {
  switch (action.type) {
    case "increment":
      return { count: state.count + action.payload };
    case "decrement":
      return { count: state.count - Number(action.payload) };
    default:
      throw new Error();
  }
}
function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: "decrement", payload: "5" })}>
        -
      </button>
      <button onClick={() => dispatch({ type: "increment", payload: 5 })}>
        +
      </button>
    </>
  );
}

хук useRef

В TypeScript, в зависимости от того, полностью ли ваш параметр типа покрывает исходное значение или нет, useRef предоставляет ссылку, доступную только для чтения или изменяемую.

function Myfunction() {
  
  const divRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
     if (!divRef.current) throw Error("divRef is not assigned");
    doSomethingWith(divRef.current);
  });
  return <div ref={divRef}>etc</div>;
}

Укажите только тип элемента в качестве аргумента и используйте null в качестве начального значения. В этом случае возвращаемая ссылка будет иметь .current только для чтения, которым управляет React. TypeScript ожидает, что вы передадите эту ссылку реквизиту ref элемента.

хук forwardRef

forwardRef — это компонент более высокого порядка, который позволяет компоненту передавать ссылку одному из своих дочерних элементов.

При использовании forwardRef важно определить типы свойств, которые передаются компоненту.

Обо мне:

Я разработчик программного обеспечения и Dev Advocate в DhiWise👩‍💻.
DhiWise позволяет создавать приложения React и Flutter с молниеносной скоростью без ущерба для качества кода и опыта разработчиков. Зайдите на платформу бесплатно, чтобы узнать больше, и не забудьте сообщить нам о своем опыте в нашем Discord🤘

Вы можете найти меня в LinkedIn и Twitter, чтобы быть в курсе последних технических обновлений о DhiWise. 😃