Перевести частину проекту з динамічного JavaScript (де змінні можуть змінювати свій тип) на строго типізований TypeScript. Навчитися описувати Інтерфейси (Interfaces) для об’єктів товарів та типізувати компоненти React, передаючи їм props.
.jsx у .tsx.Product (ідентифікатор, назва, ціна, картинка).ProductCard: вказування, що саме має прийти у props.Увага: Це ваше останнє заняття. “TechShop” майже готовий! Але коли над проектом працює ціла команда, хтось може випадково передати ціну товару як рядок "500" замість числа 500, і ваш calculateTotalAmount видасть помилку на екрані “500100” замість “600”. TypeScript це відловить ДО того як проект потрапить у браузер.
npm create vite@latest -- --template react-ts. Тут ми зробимо базовий рефакторинг існуючого файлу, щоб зрозуміти ідею).src/components/ProductCard.jsx на ProductCard.tsx (зверніть увагу, тепер розширення .tsx).У нових великих проектах типи виділяються у спеціальні папки types. Ми зробимо простіше — прямо в файлі:
// src/components/ProductCard.tsx
import { useContext } from "react";
// ...інші імпорти
// 1. Описуємо, як ДОСТЕМЕННО має виглядати товар у нашому магазині
export interface Product {
id: number;
title: string;
price: number;
image: string;
category?: string; // Знак питання означає, що це поле є НЕОБОВ'ЯЗКОВИМ
}
// 2. Описуємо Props для самого компонента (вони співпадають з Product)
interface ProductCardProps {
product: Product;
}
Нехай ваш компонент приймає замість 4-х окремих полів одразу весь об’єкт товару (щоб було легше передавати в Context):
// Вказуємо після двокрапки :React.FC<ProductCardProps>
// (FC = Function Component)
export const ProductCard: React.FC<ProductCardProps> = ({ product }) => {
const { addToCart } = useContext(CartContext);
const handleBuyClick = () => {
addToCart(product); // Тепер ніхто не передасть сюди половину об'єкта випадково!
};
return (
<article className="p-4 bg-white rounded-lg shadow-md hover:shadow-xl hover:-translate-y-1 transition flex flex-col justify-between">
{/* Якщо ви напишете product.titla - TS підкреслить червоним, бо такої властивості не заявлено */}
<img
src={product.image}
alt={product.title}
className="h-48 w-full object-contain mb-4"
/>
<h3
className="text-lg font-semibold text-gray-800 mb-2 truncate"
title={product.title}
>
{product.title}
</h3>
<p className="text-xl font-bold text-green-600 mb-4">
${product.price}
</p>
<button
className="w-full bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 rounded"
onClick={handleBuyClick}
>
Купити
</button>
</article>
);
};
Home.jsx і не передати всі аргументи, або замість id={5} передати id="п'ять", VS Code миттєво почервоніє. Код не збілдиться (npm run build).practise_1.md до practise_24.md. Ви стали справжніми інженерами “TechShop” Web Development.git add . та git commit -m "Refactor ProductCard to TypeScript and define Interfaces". Нарешті: git push origin main.Відсутність багів на виході! Якщо ви зміните назву поля бази даних price на cost, TypeScript підкаже вам про ВСІ файли в проекті (CartContext.tsx, ProductCard.tsx, Checkout.tsx), які вимагають оновлення.
Interface і чи можливо було б використати ключове слово type замість нього? У чому принципова різниця (коротко)?? (наприклад category?: string;)? Що станеться, якщо цього символу не буде, а товар прийде без категорії з FakeStoreAPI?