IlmHamroh
JavaScript Full-stack/18-qism. React chuqur34/42-dars23 daqiqa
Mundarija (35)

React + TS I: props va children turlari — type, ReactNode va React.FC munozarasi

Qisqacha: React komponentining props'i — oddiy obyekt, shuning uchun uning turi ham oddiy obyekt turi: type MenuCardProps = { name: string; price: number }. TypeScript har <MenuCard … /> ni shu tur bilan solishtiradi: yetishmagan, ortiqcha yoki noto'g'ri turdagi prop — kompilyatsiyada xato. Komponent bolalari (children) uchun eng keng tur — ReactNode (satr, son, element, null, massiv), torroq kerak bo'lsa — ReactElement. React.FC ishlaydi, lekin zamonaviy kodda props'ni to'g'ridan-to'g'ri turlash afzal: soddaroq va generic bilan ham ishlaydi.

Bu darsda

  • Props turini type yoki interface bilan yozasiz va tsc xabarlarini (TS2322, TS2741) o'qiysiz.
  • Ixtiyoriy props, standart qiymat va exactOptionalPropertyTypes tuzog'ini ko'rasiz.
  • children uchun to'g'ri turni tanlaysiz: ReactNode, ReactElement yoki PropsWithChildren.
  • React.FC haqidagi munozarani tushuntira olasiz va nega vazifalar da u yo'qligini bilasiz.
  • vazifalar da TS qadamini boshlaysiz: tsconfig'ga uchta bayroq va ikkita o'lchangan, lekin kirmagan variant.

Oldin bilishingiz kerak: children va kompozitsiya, Props, Obyekt turlari, type va interface.

1. Nega bu kerak?

Dizayn tizimi asoslari darsida «Bahor» menyusi uchun kichik komponentlar to'plami paydo bo'ldi. Endi ularni boshqalar ham ishlatadi. Sardor yangi sahifaga taom kartasini qo'ydi:

jsx
<MenuCard name="Osh" pirce={35000} />

price o'rniga pirce — bitta harf adashgan. JavaScript'da hech qanday xato chiqmaydi. Komponent price ni oladi, u esa undefined. Ekranda "Osh — so'm" chiqadi, narx yo'q. Jasur aka buni faqat mijoz shikoyat qilganda ko'radi.

Hayotiy o'xshatish: oshxonaga kelgan mahsulot yuk xati bilan keladi. Omborchi xatga qarab tekshiradi: "go'sht 10 kg, sabzi 5 kg". Biror narsa yetishmasa yoki ortiqcha bo'lsa — mahsulot qabul qilinmaguncha aniqlanadi, qozonga tushgandan keyin emas. Props turi — komponentning yuk xati. TypeScript esa omborchi: har <MenuCard … /> ni xat bilan solishtiradi.

TypeScript qismida turlarni oddiy funksiyalarga yozgan edingiz. 17-qismda vazifalar ning har komponenti .tsx da edi va props turlarini ko'rdingiz. Bu darsda shu bilimni tartibga solamiz va chuqurlashtiramiz.

2. .tsx fayl va props turi

2.1 .tsx — JSX bor TypeScript fayli

TypeScript JSX'ni faqat .tsx kengaytmali faylda tushunadi. Oddiy .ts faylda <p> — tur o'zgartirish (type assertion) sintaksisining eski shakliga o'xshaydi va tahlilchi adashadi:

ts
const el = <p>Salom</p>;

Xato:

text
TS1161: Unterminated regular expression literal.

"Tugallanmagan muntazam ifoda." Xabar g'alati tuyulishi tabiiy: .ts faylda tsc </p> dagi / ni regex boshi deb o'qidi. Qoida oddiy: komponent yoki JSX bor fayl — .tsx. Faqat mantiq (reducer, hisob, tekshiruv) — .ts. vazifalar da aynan shunday: reducer.ts, amallar.ts va App.tsx, Tugma.tsx.

2.2 Props turi — oddiy obyekt turi

Komponent — funksiya, props esa uning yagona argumenti, obyekt. Demak props turi — obyekt turi:

tsx
type MenuCardProps = {
  name: string;
  price: number;
};

function MenuCard({ name, price }: MenuCardProps) {
  return (
    <p>
      {name} — {price} so'm
    </p>
  );
}

export default function App() {
  return (
    <div>
      <MenuCard name="Osh" price={35000} />
      <MenuCard name="Manti" price={30000} />
    </div>
  );
}

Ekranda:

text
Osh — 35000 so'm
Manti — 30000 so'm

Uch narsaga qarang:

  • Nom. Tur nomi — komponent nomi + Props. Bu umumiy kelishuv: faylni ochgan har kim darhol tushunadi.
  • Destrukturizatsiya. { name, price }: MenuCardProps — tur butun obyektga yoziladi, bo'laklarga emas.
  • Qaytish turi yozilmagan. TypeScript uni o'zi chiqaradi (inference). Komponent JSX qaytarsa — tur ham to'g'ri.

2.3 Omborchi ishda: uch xil xato

Endi Sardorning xatosini va yana ikkitasini bitta faylda ko'ramiz:

tsx
type MenuCardProps = { name: string; price: number };

function MenuCard({ name, price }: MenuCardProps) {
  return <p>{name} — {price} so'm</p>;
}

export default function App() {
  return (
    <div>
      <MenuCard name="Osh" pirce={35000} />
      <MenuCard name="Manti" />
      <MenuCard name="Lag'mon" price="28000" />
    </div>
  );
}

Xato:

text
TS2322: Type '{ name: string; pirce: number; }' is not assignable to type 'IntrinsicAttributes & MenuCardProps'.
  Property 'pirce' does not exist on type 'IntrinsicAttributes & MenuCardProps'. Did you mean 'price'?
TS2741: Property 'price' is missing in type '{ name: string; }' but required in type 'MenuCardProps'.
TS2322: Type 'string' is not assignable to type 'number'.

Har birini tarjima qilamiz:

  1. "{ name; pirce } turini IntrinsicAttributes & MenuCardProps ga berib bo'lmaydi. pirce degan xususiyat yo'q. price ni nazarda tutdingizmi?" — tsc hatto to'g'ri nomni taklif qildi.
  2. "{ name } turida price yo'q, lekin MenuCardProps da u majburiy." — yetishmagan prop.
  3. "string ni number ga berib bo'lmaydi." — price="28000" qo'shtirnoqda, ya'ni satr. Son kerak bo'lsa — price={28000}.

Birinchi xabardagi IntrinsicAttributes nima? Bu — React har komponentga o'zi qo'shadigan atributlar, asosan key. Shuning uchun <MenuCard key="1" … /> ham xatosiz: key props turida yo'q, lekin IntrinsicAttributes da bor. & — kesishma: "ikkalasining hamma xususiyati".

Tekshirib ko'ring: Uchinchi xabar nega MenuCardProps ni emas, faqat string va number ni tilga oldi?

Javob

Chunki obyektning shakli to'g'ri: name ham, price ham bor. Muammo bitta xususiyatning qiymatida. tsc xatoni eng aniq joyga — price="28000" ga qo'yadi va faqat shu qiymat turini aytadi. Qator va ustun raqami (index.tsx(10,32)) ham aynan price ni ko'rsatadi.

2.4 type yoki interface?

Props'ni interface bilan ham yozish mumkin, ikkalasi deyarli bir xil ishlaydi:

tsx
interface DishProps {
  name: string;
  price: number;
}

function Dish({ name, price }: DishProps) {
  return <li>{name}: {price}</li>;
}

export default function App() {
  return (
    <ul>
      <Dish name="Ko'k choy" price={5000} />
    </ul>
  );
}

Ekranda:

text
Ko'k choy: 5000

Farq props uchun kam uchraydi. Asosiysi: type union bo'la oladi (A | B), interface esa yo'q. 37-darsda props'ni aynan union qilamiz (React + TS IV). interface ning o'z kuchi — declaration merging, unga 38-darsda yetamiz (Kutubxona turlari). Loyiha ichida bittasini tanlab, izchil bo'lish muhim. vazifalar da props — type.

3. Ixtiyoriy props va standart qiymat

3.1 ? va standart qiymat

Ba'zi props'ni berish shart emas. Masalan, taom yonidagi yorliq: ko'pincha "yangi", lekin boshqa matn ham bo'lishi mumkin. Ixtiyoriy xususiyat — ? bilan, standart qiymat esa destrukturizatsiyada:

tsx
type BadgeProps = {
  label: string;
  tone?: "yashil" | "qizil";
};

function Badge({ label, tone = "yashil" }: BadgeProps) {
  return (
    <p>
      [{tone}] {label}
    </p>
  );
}

export default function App() {
  return (
    <div>
      <Badge label="Yangi" />
      <Badge label="Tugadi" tone="qizil" />
    </div>
  );
}

Ekranda:

text
[yashil] Yangi
[qizil] Tugadi

Komponent ichida tone turi — "yashil" | "qizil", undefined emas. Standart qiymat bo'shliqni yopdi va TypeScript buni tushunadi. Funksiya komponentlarida standart qiymatning yagona to'g'ri joyi — shu. Eski kodda Badge.defaultProps = { … } ni ko'rasiz. React 19 uni funksiya komponentlarida olib tashlagan, u class komponentlarda qoldi (Class komponentlar).

3.2 exactOptionalPropertyTypes tuzog'i

vazifalar ning tsconfig.app.json ida bitta qat'iy bayroq bor: exactOptionalPropertyTypes (Strict bayroqlar oilasi). U tone?: … ni "berilmasligi mumkin" deb o'qiydi, lekin "undefined berilishi mumkin" deb emas. Farqi ota komponentda chiqadi:

tsx
// @ts-options: {"exactOptionalPropertyTypes": true}
type BadgeProps = { label: string; tone?: "yashil" | "qizil" };

function Badge({ label, tone = "yashil" }: BadgeProps) {
  return <p>[{tone}] {label}</p>;
}

function DishBadge({ soldOut }: { soldOut: boolean }) {
  const tone = soldOut ? "qizil" : undefined;
  return <Badge label="Osh" tone={tone} />;
}

export default DishBadge;

Xato:

text
TS2375: Type '{ label: string; tone: "qizil" | undefined; }' is not assignable to type 'BadgeProps' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.

"Bu tur exactOptionalPropertyTypes: true bilan BadgeProps ga mos emas. Nishon xususiyatlari turiga undefined qo'shishni o'ylab ko'ring." Ikki yo'l bor:

  • Komponent tomonda: tone?: "yashil" | "qizil" | undefined. Endi undefined ni ochiq uzatish ham mumkin. Qayta ishlatiladigan komponentlar uchun shu qulay — ota tomonda shart yozish shart emas. vazifalar dagi Tugma da aynan shunday: ref?: Ref<HTMLButtonElement> | undefined.
  • Ota tomonda: prop'ni umuman bermaslik — {...(soldOut ? { tone: "qizil" } : {})}. Bu noqulay, shuning uchun birinchisi ko'proq uchraydi.

Nega bu bayroq kerak? U "xususiyat yo'q" va "xususiyat bor, qiymati undefined" ni ajratadi. "tone" in props va Object.keys uchun bu ikki holat farq qiladi (Obyekt metodlari). Bayroq farqni ko'rinadigan qiladi.

3.3 readonly props

Props — faqat o'qish uchun: komponent ularni o'zgartirmaydi. TypeScript buni readonly bilan majburlay oladi:

tsx
type PriceProps = { readonly price: number };

function Price(props: PriceProps) {
  props.price = 0;
  return <p>{props.price}</p>;
}

export default function App() {
  return <Price price={35000} />;
}

Xato:

text
TS2540: Cannot assign to 'price' because it is a read-only property.

"price ga yozib bo'lmaydi — u faqat o'qiladigan xususiyat". Amalda ko'p jamoalar har prop'ga readonly yozmaydi: destrukturizatsiya qilingan price baribir mahalliy o'zgaruvchi, uni o'zgartirish props'ga tegmaydi. readonly ko'proq massiv props uchun foydali: items: readonly Dish[] — komponent ichida items.push(…) endi xato. vazifalar da shunday: boshlangichRoyxat: readonly VazifaMalumoti[].

4. children turlari

4.1 ReactNode — eng keng tur

children va kompozitsiya darsida children: ReactNode deb yozgan edik. Endi ichiga qaraymiz. ReactNode — JSX'da {} ichiga qo'yish mumkin bo'lgan hamma narsa. Diagrammada uning tarkibi (@types/react 19.3.0 ta'rifidan):

flowchart TD
  N["ReactNode"] --> E["ReactElement: &lt;p&gt;, &lt;MenuCard /&gt;"]
  N --> S["string, number, bigint"]
  N --> B["boolean, null, undefined: hech narsa chizilmaydi"]
  N --> I["Iterable&lt;ReactNode&gt;: massiv"]
  N --> P["ReactPortal: createPortal natijasi"]
  N --> R["Promise: use() bilan, 18/04"]

Pastki qatordagi ikkitasiga e'tibor bering. ReactPortal — Portallar darsidagi createPortal natijasi. Promise esa React 19 da qo'shildi: Suspense ichida Promise ham bola bo'la oladi (use()). Diagrammada yo'q narsa — oddiy obyekt va funksiya. Ular ReactNode emas, shuning uchun {order} va {getPrice} tsc xatosi beradi (JSX II).

Ko'p hollarda children: ReactNode — to'g'ri tanlov. Karta, panel, modal, layout — ichiga istalgan narsa tushadi.

4.2 children turida bo'lmasa

Props turida children bo'lmasa, komponent bola qabul qilmaydi:

tsx
function Title({ text }: { text: string }) {
  return <h2>{text}</h2>;
}

export default function App() {
  return <Title text="Bugungi menyu">35 000 so'm</Title>;
}

Xato:

text
TS2322: Type '{ text: string; children: string; }' is not assignable to type 'IntrinsicAttributes & { text: string; }'.
  Property 'children' does not exist on type 'IntrinsicAttributes & { text: string; }'.

"children xususiyati { text: string } turida yo'q." Bu foydali: JS'da "35 000 so'm" jim yo'qolib ketardi, chunki Title uni hech qayerga chiqarmaydi. TypeScript ochiq-oydin aytdi.

4.3 ReactElement — faqat element

Ba'zan bola faqat element bo'lishi kerak, matn emas. Masalan, Tooltip bolasiga aria-describedby qo'shmoqchi. Buning uchun bola element bo'lishi shart:

tsx
import type { ReactElement } from "react";

function Tooltip({ children }: { children: ReactElement }) {
  return <span className="tooltip">{children}</span>;
}

export default function App() {
  return <Tooltip>Osh</Tooltip>;
}

Xato:

text
TS2747: 'Tooltip' components don't accept text as child elements. Text in JSX has the type 'string', but the expected type of 'children' is 'ReactElement<unknown, string | JSXElementConstructor<any>>'.

"Tooltip komponenti matnni bola sifatida qabul qilmaydi. JSX'dagi matn — string, kutilgan tur esa ReactElement." <Tooltip><button>Osh</button></Tooltip> — xatosiz.

Bitta muhim cheklov. ReactElement faqat "bu element" deydi. "Bu <button>" yoki "bu <MenuCard />" deb talab qila olmaydi. JSX ifodasining turi doim umumiy JSX.Element — tsc qaysi komponentdan yasalganini eslab qolmaydi. Shuning uchun children: ReactElement<ButtonProps> yozsangiz ham, <Tooltip><div /></Tooltip> o'tib ketadi. Aniq turdagi bolani talab qilish kerak bo'lsa — boshqa yo'l: slot prop yoki compound komponent (Compound komponentlar).

4.4 JSX.Element va qaytish turi

Ba'zi kodda komponent qaytish turi ochiq yozilgan: function Icon(): JSX.Element. JSX.Element — bitta JSX ifodasi turi. Unda null yo'q:

tsx
import type { JSX } from "react";

function Discount({ percent }: { percent: number }): JSX.Element {
  if (percent === 0) return null;
  return <b>-{percent}%</b>;
}

export default function App() {
  return <Discount percent={10} />;
}

Xato:

text
TS2322: Type 'null' is not assignable to type 'Element'.

Komponent null ham, satr ham qaytara oladi. Shuning uchun qaytish turini yozmoqchi bo'lsangiz — ReactNode. Yaxshisi esa — umuman yozmaslik: TypeScript uni o'zi chiqaradi. React ham komponent ReactNode qaytarishini kutadi.

Tur Nima kiradi Qachon
ReactNode hammasi: matn, son, element, null, massiv children, slot prop'lar
ReactElement faqat element bolani klonlash yoki o'rash kerak bo'lsa
JSX.Element bitta JSX ifodasi eski kodda qaytish turi
string faqat matn title, label kabi oddiy matnlar

4.5 PropsWithChildren

@types/react da kichik yordamchi tur bor: PropsWithChildren<P>. U P ga children?: ReactNode qo'shadi:

tsx
import type { PropsWithChildren } from "react";

type PanelProps = PropsWithChildren<{ title: string }>;

function Panel({ title, children }: PanelProps) {
  return (
    <section>
      <h2>{title}</h2>
      {children}
    </section>
  );
}

export default function App() {
  return (
    <Panel title="Ichimliklar">
      <p>Ko'k choy — 5000 so'm</p>
    </Panel>
  );
}

Ekranda:

text
Ichimliklar
Ko'k choy — 5000 so'm

Qulay, lekin bir nozik joyi bor: children bu yerda ixtiyoriy. <Panel title="Bo'sh" /> ham xatosiz o'tadi. Bo'sh panel ma'nosiz bo'lsa — children: ReactNode ni o'zingiz, ? siz yozing. Ko'p jamoalar shu sababli PropsWithChildren dan ko'ra ochiq children: ReactNode ni afzal ko'radi: tur nima talab qilishi bir qarashda ko'rinadi.

Tekshirib ko'ring: type CardProps = { children: ReactNode } bo'lsa, <Card /> (bolasiz) xato beradimi? <Card>{null}</Card>-chi?

Javob

<Card /> — xato (TS2741: Property 'children' is missing…): xususiyat majburiy, lekin umuman berilmagan. <Card>{null}</Card> esa xatosiz: children berildi, qiymati null, null esa ReactNode ga kiradi. Demak children: ReactNode "bo'sh bo'lmasin" degani emas, faqat "yozilishi shart" degani. Haqiqatan bo'sh emasligini tekshirish — ish vaqtidagi mantiq.

5. React.FC munozarasi

5.1 Ikki yozuv

Internetdagi ko'p misolda komponent boshqacha yozilgan:

tsx
import type { FC } from "react";

type PriceTagProps = { price: number };

const PriceTag: FC<PriceTagProps> = ({ price }) => {
  return <p>{price} so'm</p>;
};

export default function App() {
  return <PriceTag price={28000} />;
}

Ekranda:

text
28000 so'm

FC — "function component" turi (to'liq nomi FunctionComponent). U o'zgaruvchiga tur beradi: "bu — props'i PriceTagProps bo'lgan komponent". Ishlaydi. Unda nega kurs va vazifalar uni ishlatmaydi?

5.2 Tarix: yashirin children

2022-yilgacha (@types/react 18 dan oldin) FC har komponentga yashirin children qo'shardi. <PriceTag price={1}>matn</PriceTag> xatosiz o'tardi, matn esa jim yo'qolardi — «children turida bo'lmasa» bo'limidagi himoya ishlamasdi. Shuning uchun ko'p jamoa FC dan voz kechdi. Hozir children olib tashlangan va FC ham bolasiz komponentni to'g'ri tekshiradi:

tsx
import type { FC } from "react";

const Card: FC<{ title: string }> = ({ title, children }) => (
  <section>
    <h2>{title}</h2>
    {children}
  </section>
);

export default function App() {
  return <Card title="Osh" />;
}

Xato:

text
TS2339: Property 'children' does not exist on type '{ title: string; }'.

Eski darslikdagi FC kodini ko'chirsangiz, aynan shu xatoni olasiz. Davosi — children ni props turiga o'zingiz yozish.

5.3 Bugungi tanlov

function X(props: XProps) const X: FC<XProps>
children turda yozilsa bor turda yozilsa bor (18 dan)
generic komponent function List<T>(…) FC ni generic qilib bo'lmaydi
hoisting e'londan oldin ishlatsa bo'ladi const — oldin emas
displayName turi yo'q (kerak emas) bor

Asosiy farq — ikkinchi qator. Generic komponent (<List<Dish> items={…} />) React + TS IV darsida kerak bo'ladi va FC bilan yozib bo'lmaydi. Shuning uchun bu kursda — oddiy funksiya va turlangan props. FC ni begona kodda ko'rsangiz — xato emas, shunchaki boshqa uslub. Uni "to'g'rilash" uchun kodni qayta yozish shart emas.

6. Props turini qayta ishlatish

Ba'zan boshqa komponentning props turi kerak bo'ladi. Masalan, MenuCard ni o'raydigan FeaturedCard yozyapsiz. Tur eksport qilinmagan bo'lsa ham, ComponentProps bilan uni komponentdan "sug'urib olish" mumkin:

tsx
import type { ComponentProps } from "react";

function MenuCard({ name, price }: { name: string; price: number }) {
  return <p>{name} — {price} so'm</p>;
}

type MenuCardProps = ComponentProps<typeof MenuCard>;

function FeaturedCard(props: MenuCardProps) {
  return (
    <div>
      <b>Kun taomi:</b>
      <MenuCard {...props} />
    </div>
  );
}

export default function App() {
  return <FeaturedCard name="Lag'mon" price={28000} />;
}

Ekranda:

text
Kun taomi:
Lag'mon — 28000 so'm

typeof MenuCard — funksiyaning turi (typeof turlarda). ComponentProps undan birinchi argument turini chiqaradi. Ichida infer bor: T extends JSXElementConstructor<infer Props> ? Props : …. Xuddi shu yordamchi HTML teglari uchun ham ishlaydi: ComponentProps<"button"> — <button> ning hamma atributlari. Bu — keyingi darsdan keyingi mavzu (React + TS III).

7. Vazifalar qadami: TS qadami boshlanadi

7.1 Besh dars — bitta branch

34–38-darslar vazifalar da bitta qadam: refactor/turlar branch'i. Har dars o'z bo'lagini qo'shadi, commit — 38-darsda. Bugungi bo'lak — tur tekshiruvini qat'iyroq qilish:

bash
git switch -c refactor/turlar

Avval mavjud props'ga qarang. App ning props turi:

tsx
type Props = {
  boshlangichRoyxat: readonly VazifaMalumoti[]; // localStorage'dan
  qoralama: string; // forma ochilgandagi matn
};

Bugungi darsning hamma qoidasi bor: type, nom — Props (fayl ichida bitta komponent), massiv — readonly, children yo'q (App bola qabul qilmaydi), React.FC yo'q.

7.2 Uch yangi bayroq — o'lchab qo'shildi

tsconfig.app.json da strict dan tashqari yana yettita bayroq bor edi (15/#34 va 16/#42). Kanon yana uchtasini sinab ko'rdi. Har bayroq yoqilib, tsc -b ishga tushirildi va xatolar sanaldi (natijalar/38-turlar.txt). Bayroqlar nima qilishini avval kichik faylda ko'ramiz:

ts
// @ts-options: {"allowUnreachableCode": false}
import "./tema-yoq.ts";

function price(): number {
  return 35000;
  console.log("hech qachon");
}

console.log(price());

Xato:

text
TS2882: Cannot find module or type declarations for side-effect import of './tema-yoq.ts'.
TS7027: Unreachable code detected.
  • TS2882 — "yon ta'sirli import (import "./fayl", nomsiz) fayli topilmadi". Bu noUncheckedSideEffectImports. Nomli importni tsc doim tekshiradi, nomsizini esa ilgari o'tkazib yuborardi. Fayl nomida xato bo'lsa — build'da jim yo'qolardi.
  • TS7027 — "yetib bo'lmaydigan kod". Bayroqsiz bu faqat muharrirdagi xira ko'rinish, allowUnreachableCode: false esa uni xatoga aylantiradi.
  • Uchinchi bayroq — allowUnusedLabels: false. Hech qayerda break tashqi bilan ishlatilmagan tashqi: label'i — TS7028: Unused label. xatosi.

To'rtinchi bayroq boshqacha — u xato emas, yozish uslubini tekshiradi:

ts
// @ts-options: {"noPropertyAccessFromIndexSignature": true}
const li = document.createElement("li");
li.dataset.id = "7";
console.log(li.dataset.id, li.dataset["id"]);

Xato:

text
TS4111: Property 'id' comes from an index signature, so it must be accessed with ['id'].
TS4111: Property 'id' comes from an index signature, so it must be accessed with ['id'].

"id index signature'dan keladi (Index signature), uni ['id'] bilan o'qing." dataset — har qanday nomni qabul qiladigan obyekt. Bayroq "bunday nom bor-yo'qligi noma'lum, buni ko'rinib tursin" deydi. Qavsli li.dataset["id"] — xatosiz.

Bitta kuzatuv. Biz noUncheckedSideEffectImports ni yoqmadik, lekin TS2882 baribir chiqdi. tsc 7.0.2 da bu tekshiruv standart holatda yoqilgan. Kanon uni baribir aniq yozdi: sozlama faylni o'qigan odam qaror ko'rinib tursin.

Endi vazifalar dagi haqiqiy natija:

Bayroq vazifalar da xato Qaror
noUncheckedSideEffectImports 0 kirdi
allowUnreachableCode: false 0 kirdi
allowUnusedLabels: false 0 kirdi
noPropertyAccessFromIndexSignature 20 (hammasi TS4111) kirmadi

Uchtasi — "bepul himoya": bugun 0 xato, ertangi xatoni ushlaydi. To'rtinchisi 20 joyda dataset.id ni dataset["id"] ga o'zgartirishni talab qildi. Bu xato topmaydi, faqat yozish uslubini o'zgartiradi. Shuning uchun kirmadi, sababi izohda yozildi:

json
// 18/#34: yana uchta — o'lchandi, kanonda 0 xato (bepul himoya):
// yon ta'sirli import fayli yo'q bo'lsa xato, yetib bo'lmaydigan kod
// va ishlatilmagan label — xato (ogohlantirish emas).
// noPropertyAccessFromIndexSignature (20 joy — dataset.id ni
// dataset["id"] qilish) va typescript-eslint strictTypeChecked (70,
// hammasi uslub) — o'lchandi, kiritilmadi (natijalar/38-*)
"noUncheckedSideEffectImports": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,

7.3 strictTypeChecked — 70 topilma, 0 xato

Izohdagi ikkinchi o'lchov — ESLint tomonda. vazifalar da typescript-eslint'ning recommendedTypeChecked to'plami ishlaydi (ESLint II). Undan qat'iyroq — strictTypeChecked. U vaqtincha yoqildi va src/ da 70 topilma berdi:

strictTypeChecked: vazifalar src/ dagi topilmalar
  • no-confusing-void-expression40 ta
  • restrict-template-expressions24 ta
  • no-unnecessary-condition4 ta
  • no-meaningless-void-operator2 ta

Manba: vazifalar v8, natijalar/38-turlar.txt — typescript-eslint 8.71.1, 2026-10-13

Grafikdagi eng uzun ikki ustun — uslub. no-confusing-void-expression () => setOchiq(false) kabi qisqa strelkalarni yoqtirmaydi. restrict-template-expressions esa shablon satrga son qo'yishni (`${narx} so'm`) taqiqlaydi. no-unnecessary-condition ning 4 tasi ko'rib chiqildi: biri ataylab yozilgan never tekshiruvi (37-darsda), qolganlari lib.dom turlari bilan bog'liq. Real xato — 0. Qaror: kirmadi. Bu "o'lchab qaror qilish" — xuddi React Compiler darsidagidek: qoida qanchalik qat'iy bo'lmasin, foydasini raqam bilan ko'rsatmasa, kodga yuk bo'ladi.

Tekshirib ko'ring: Nega noPropertyAccessFromIndexSignature "kirmadi", allowUnreachableCode: false esa "kirdi" — ikkalasi ham xato ushlaydigan bayroq emasmi?

Javob

Mezon — narx va foyda. Bayroq allowUnreachableCode: false bugun 0 o'zgarish talab qildi, ertaga esa haqiqiy xatoni (masalan, return dan keyin qolgan kod) ushlaydi. Bayroq noPropertyAccessFromIndexSignature esa 20 joyni o'zgartirishni talab qildi va ularning birortasi ham xato emas edi: dataset.id va dataset["id"] bir xil ishlaydi. Narx bor, foyda ko'rinmadi.

Tekshiruvlar (shu bo'lakdan keyin, kanon): npm run tip — 0 xato, npm run lint va npm test — o'zgarishsiz toza. Commit hali yo'q.

8. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
TS1161: Unterminated regular expression literal JSX .ts faylda fayl kengaytmasi — .tsx
TS2322 … Did you mean 'price'? prop nomida xato tsc taklif qilgan nom
TS2741: Property 'x' is missing majburiy prop berilmagan prop'ni bering yoki turda x?
TS2375 … exactOptionalPropertyTypes ixtiyoriy prop'ga undefined uzatildi turga | undefined qo'shing
TS2322 … 'children' does not exist turda children yo'q children: ReactNode qo'shing
TS2339: Property 'children' does not exist eski FC kodi children ni turga yozing
TS2322: Type 'null' is not assignable to type 'Element' qaytish turi JSX.Element ReactNode yoki tursiz

9. Mashqlar

Mashqlar kurs/mashqlar/18/34-props-turlari/ da. Har yechimni «Ishga tushir» bilan sinang, tip xatolarini esa «TS Playground'da ochish» yoki o'z loyihangizda npm run tip bilan.

1-mashq (oson): qaysi tur?

Har holatga mos turni yozing: ReactNode, ReactElement yoki string.

  • Kartaning sarlavhasi — faqat matn, <h2> ga qo'yiladi.
  • Modal oynaning ichi — matn, forma, rasm, hammasi bo'lishi mumkin.
  • Tooltip bolasi — unga aria-describedby qo'shib klonlanadi.
Yechim
  • string — sarlavha faqat matn bo'lsa, eng tor tur eng aniq. <b> kerak bo'lib qolsa — ReactNode ga kengaytirasiz.
  • ReactNode — modal ichiga istalgan narsa tushadi, bu children ning odatiy turi.
  • ReactElement — klonlash uchun element kerak, matn emas (TS2747 himoyasi). Lekin aniq qaysi element ekanini bu tur kafolatlamaydi.

2-mashq (o'rta): kartaga tur yozing

OrderLine komponentiga props turi yozing: dish (satr, majburiy), count (son, ixtiyoriy, standart 1), note (ixtiyoriy, istalgan ReactNode). note bo'lsa — qator ostida <small> da chiqsin. Ishora: standart qiymat — destrukturizatsiyada («? va standart qiymat» bo'limi), note uchun && (Shartli render).

tsx
export default function App() {
  return (
    <ul>
      <OrderLine dish="Osh" count={2} />
      <OrderLine dish="Ko'k choy" note={<i>shakarsiz</i>} />
    </ul>
  );
}
Yechim
tsx
import type { ReactNode } from "react";

type OrderLineProps = {
  dish: string;
  count?: number;
  note?: ReactNode;
};

function OrderLine({ dish, count = 1, note }: OrderLineProps) {
  return (
    <li>
      {dish} × {count}
      {note && <small> ({note})</small>}
    </li>
  );
}

export default function App() {
  return (
    <ul>
      <OrderLine dish="Osh" count={2} />
      <OrderLine dish="Ko'k choy" note={<i>shakarsiz</i>} />
    </ul>
  );
}

Ekranda:

text
Osh × 2
Ko'k choy × 1 (shakarsiz)

Komponent ichida count turi — number: standart qiymat undefined ni yopdi. Prop note esa ReactNode, shuning uchun unga element ham (<i>), matn ham berish mumkin. Bitta nozik joy: note ga son berilsa, 0 && tuzog'i (JSX II) qaytadi. Qat'iy bo'lish uchun note !== undefined && yozing.

3-mashq (qiyin): FC kodni ko'chirish

Eski loyihadan ko'chirilgan kod tsc'dan o'tmayapti:

tsx
import type { FC } from "react";

type SectionProps = { title: string; empty?: boolean };

const Section: FC<SectionProps> = ({ title, empty, children }) => (
  <section>
    <h2>{title}</h2>
    {empty ? <p>Hozircha bo'sh</p> : children}
  </section>
);

export default function App() {
  return (
    <Section title="Shirinliklar">
      <p>Chak-chak</p>
    </Section>
  );
}

Xato:

text
TS2339: Property 'children' does not exist on type 'SectionProps'.
TS2322: Type '{ title: string; children: Element; }' is not assignable to type 'IntrinsicAttributes & SectionProps'.
  Property 'children' does not exist on type 'IntrinsicAttributes & SectionProps'.

Kodni bugungi uslubga o'tkazing: FC siz, oddiy function, children turda ochiq va majburiy. Nega eski kod qachonlardir ishlagan edi — bir gap bilan tushuntiring.

Yechim
tsx
import type { ReactNode } from "react";

type SectionProps = {
  title: string;
  empty?: boolean;
  children: ReactNode;
};

function Section({ title, empty = false, children }: SectionProps) {
  return (
    <section>
      <h2>{title}</h2>
      {empty ? <p>Hozircha bo'sh</p> : children}
    </section>
  );
}

export default function App() {
  return (
    <Section title="Shirinliklar">
      <p>Chak-chak</p>
    </Section>
  );
}

Ekranda:

text
Shirinliklar
Chak-chak

Eski kod @types/react 17 va undan oldin ishlagan. O'shanda FC har komponentga yashirin children?: ReactNode qo'shardi. Versiya 18 da bu olib tashlandi, shuning uchun ikki xato chiqdi. Biri komponent ichida (children ni o'qish), biri ishlatilgan joyda (children berish). Yechimdagi empty = false — ixtiyoriy boolean uchun aniq standart. Bu shart emas (undefined ham "yolg'on"), lekin o'qishni osonlashtiradi.

4-mashq: Vazifalar qadami

refactor/turlar branch'ini oching. tsconfig.app.json ga uchta bayroqni izohi bilan qo'shing (Vazifalar qadami bo'limidagi parcha). Keyin o'lchang: avval noPropertyAccessFromIndexSignature ni ham vaqtincha qo'shib, npm run tip dagi TS4111 larni sanang, so'ng uni olib tashlang.

Yechim

Tekshiruv ro'yxati:

  • Uch bayroq bilan npm run tip — 0 xato.
  • Vaqtincha noPropertyAccessFromIndexSignature bilan — TS4111 lar (kanonda 20 ta: App.tsx dagi dataset.id, dataset.amal, paket.ts dagi Record<string, unknown> o'qishlari). Sizda raqam boshqacha bo'lishi mumkin, agar kodingiz kanondan farq qilsa.
  • Bayroq olib tashlandi, izohda — nega kirmagani. npm run lint, npm test — toza.
  • Commit hali yo'q — 38-darsda, beshta bo'lak bilan birga.

10. Real ishda

  • Kod ko'rigi (code review) da birinchi qaraladigan joylardan biri — komponentning props turi. U komponentning "shartnomasi": nima majburiy, nima ixtiyoriy, children qanday.
  • Dizayn tizimlari (MUI, Mantine, Radix) props turlarini eksport qiladi: ButtonProps. Eksport qilinmagan bo'lsa — ComponentProps<typeof Button>.
  • React.FC munozarasi intervyuda tez-tez so'raladi: "FC ishlatasizmi, nega?". Javob: "props'ni to'g'ridan-to'g'ri turlayman — generic bilan ishlaydi, children turda ochiq".
  • tsconfig bayroqlari — yangi loyihada create-vite shablonidan boshlanadi, keyin jamoa o'lchab qo'shadi. "Hamma bayroqni yoqish" ham, "hech birini" ham — yomon qaror.

Xulosa

  • Props turi — oddiy obyekt turi: type XProps = { … }, komponentda ({ a, b }: XProps).
  • Ixtiyoriy — ?, standart qiymat — destrukturizatsiyada. exactOptionalPropertyTypes da undefined uzatish uchun — | undefined.
  • children: odatda ReactNode, faqat element — ReactElement, faqat matn — string. Turda bo'lmasa — bola qabul qilinmaydi.
  • React.FC ishlaydi, lekin generic bo'lmaydi; zamonaviy uslub — turlangan props bilan oddiy funksiya.
  • vazifalar: refactor/turlar boshlandi — uch tsc bayrog'i kirdi (0 xato), noPropertyAccessFromIndexSignature (20) va strictTypeChecked (70, real xato 0) — kirmadi.

Keyingi dars: React + TS II: hooklar turlari — useState, useRef, useReducer va Context'ga tur berish va null tuzog'i.

Manbalar

  • React: "Using TypeScript" — react.dev/learn/typescript (2026-10 holatiga, React 19.3)
  • TypeScript: exactOptionalPropertyTypes — typescriptlang.org/tsconfig#exactOptionalPropertyTypes
  • TypeScript: noUncheckedSideEffectImports — typescriptlang.org/tsconfig#noUncheckedSideEffectImports
  • @types/react 19.3.0 — ReactNode, PropsWithChildren, FunctionComponent ta'riflari (index.d.ts)
  • typescript-eslint: Shared Configs (strict-type-checked) — typescript-eslint.io/users/configs
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
React + TS I: props va children turlari — type, ReactNode va React.FC munozarasi — IlmHamroh