Вы написали компонент карточки заметки. Он получает объект, выводит заголовок и описание. Всё работает.
Затем в приложении появляется ещё один источник данных. У новой заметки нет описания или поле заголовка называется иначе. В JavaScript проблема обнаружится, когда соответствующие данные попадут в интерфейс.
TypeScript позволяет увидеть часть таких ошибок раньше, ещё во время разработки. Разберём это на небольшом React-компоненте.
Начинаем с данных
Представим приложение для заметок. Каждая заметка содержит идентификатор, заголовок и, возможно, описание.
Опишем её тип.
type Note = {
id: string;
title: string;
description?: string;
};
Здесь id и title обязательны. А знак ? возле description означает, что описание может отсутствовать.
Например, оба объекта соответствуют этому типу.
const firstNote: Note = {
id: "1",
title: "План проекта",
description: "Подготовить первую версию",
};
const secondNote: Note = {
id: "2",
title: "Идеи на завтра",
};
Вторую заметку можно показать без ошибки. Но компонент должен понимать, что описание у неё не гарантировано.
Передаём заметку в React-компонент
Теперь создадим карточку, которая принимает объект заметки через props.
type Note = {
id: string;
title: string;
description?: string;
};
type NoteCardProps = {
note: Note;
};
function NoteCard({ note }: NoteCardProps) {
return (
<article>
<h2>{note.title}</h2>
<p>{note.description ?? "Без описания"}</p>
</article>
);
}
const note: Note = {
id: "1",
title: "План проекта",
};
export default function NotesPage() {
return <NoteCard note={note} />;
}
Компонент получает объект, структура которого заранее описана в NoteCardProps. Оператор ?? задаёт запасной текст. Когда description равно undefined или null, на странице появится «Без описания».
Нам не требуется отдельный сложный механизм для необязательного поля. Достаточно описать реальную структуру данных и учесть её в интерфейсе.
Как TypeScript показывает ошибку
Допустим, кто-то передал карточке такую заметку.
const note: Note = {
id: "3",
name: "Список задач",
};
Здесь вместо title указано name. TypeScript сообщит, что объект не соответствует ожидаемому типу. Для Note обязателен title, а поле name в его описании отсутствует. Это нужно, чтобы не увидеть пустой заголовок уже в браузере и искать причину по всему приложению.
Похожая ситуация возникает, когда компонент ждёт строку, а получает число.
const note: Note = {
id: "4",
title: 123,
};
Здесь значение 123 не подходит для свойства title, которое объявлено как string.
В редакторе можно увидеть сообщение вида Type 'number' is not assignable to type 'string'. TypeScript показывает место, где две части приложения не договорились о данных.
Почему any это плохо
При первых ошибках TypeScript появляется соблазн написать as any и продолжить работу. Это убирает часть проверок, но не исправляет объект. Если в данных нет заголовка, компонент по-прежнему не получит заголовок. Просто редактор перестанет предупреждать об этом. Нужно разобраться, почему структура отличается.
Возможно, API вернул поле name, а интерфейс ожидает title. Тогда стоит привести внешний ответ к внутреннему типу приложения. Возможно, поле действительно необязательное. Тогда это нужно явно отразить в типе и предусмотреть поведение компонента. Так типы становятся понятным соглашением между частями проекта.
А если данные пришли с сервера
В Next.js данные часто загружаются на сервере, а затем передаются в компоненты интерфейса. Например, сервер получает список заметок из API. Один компонент отвечает за загрузку, другой за отображение карточки. Тип Note помогает описать, что именно получает интерфейс.
Но здесь есть граница возможностей TypeScript. Он проверяет код во время разработки, а не содержимое произвольного JSON во время работы приложения. Если внешний API неожиданно вернул неправильную структуру, TypeScript сам по себе её не исправит.
Для таких данных нужна проверка при получении. Например, с помощью Zod. После этого приложение работает с предсказуемой внутренней моделью.
Отдельно разбирать Zod здесь не будем. В статье «Как сделать форму с понятными ошибками в React» уже показано, как схема помогает проверять ввод пользователя.
Что происходит, когда приложение растёт
В маленьком компоненте описать тип просто. В большом проекте количество связей увеличивается. Данные проходят через сервер, страницы, компоненты, формы и операции сохранения. Один объект используется сразу в нескольких местах. Надо понимать, где формируется структура данных и какие части приложения от неё зависят.
В Next.js App Router это заметно на границе серверных и клиентских компонентов. TypeScript помогает сделать передачу данных более предсказуемой.
В моей статье на Habr о TypeScript как системе контрактов эта идея разобрана глубже на примерах Next.js.
От карточки заметки до полноценного приложения
Карточка с двумя полями показывает принцип, на котором держится большой интерфейс. Компонент должен получать данные понятной структуры. Изменения в этой структуре должны обнаруживаться до того, как они сломают соседние части приложения.
В Workbench Notes эти идеи используются при работе с заметками, проектами, формами и серверными операциями.
Курс «Next.js II: TypeScript 2026» последовательно развивает этот подход. От типов данных и компонентов до Server Actions, управления состоянием и архитектуры приложения.
TypeScript не избавляет от всех ошибок. Зато помогает увидеть несоответствия между частями программы раньше и исправлять их там, где они возникли.