11-bo‘lim
Modullar
export va import, tur importlari, barrel fayllar, global soha tuzog'i va doiraviy bog'liqlik.
Ushbu bo‘lim mundarijasi
Hozirgacha har bir misol bitta faylda edi. Haqiqiy loyihada kod o'nlab fayllarga bo'linadi va ular bir-birini chaqiradi.
TypeScript ES modullaridan foydalanadi - export va import.
Ularga u bitta muhim narsa qo'shadi: tur importlari.
export va import #
export const QQS = 12;
export function qqsBilan(narx: number): number {
return narx * (1 + QQS / 100);
}
import { QQS, qqsBilan } from "./narx";
console.log(QQS, qqsBilan(10000).toFixed(0));
tsx src/asosiy.ts
12 11200
Import yo'li - "./narx", fayl nomi esa narx.ts.
Kengaytmasiz yozildi; nega bunday ekanini quyida ko'ramiz.
Standart eksport #
export const manzil = "Toshkent";
export default class Dokon {
constructor(public nomi: string) {}
}
import Dokon, { manzil } from "./dokon";
const d = new Dokon("Husanboy dokoni");
console.log(d.nomi, manzil);
tsx src/asosiy.ts
Husanboy dokoni Toshkent
Bir faylda bitta default va istalgancha nomli eksport bo'lishi
mumkin.
import Dokon from "./dokon" da Dokon - siz o'ylab topgan
nom. Xohlasangiz import Magazin from "./dokon" deb ham
yozasiz.
Bu erkinlik qulay tuyuladi, lekin:
- bir narsa loyihaning turli joylarida turlicha nomlanadi;
- qayta nomlash vositalari ishlamay qoladi;
- avtomatik import taklifi zaiflashadi.
Ko'p jamoalar faqat nomli eksport ishlatadi. Bu darslikda ham shunday qilamiz.
Nom fazosi va qayta nomlash #
export const QQS = 12;
export function qqsBilan(narx: number): number {
return narx * (1 + QQS / 100);
}
import * as narx from "./narx";
import { QQS as soliq } from "./narx";
console.log(narx.QQS, narx.qqsBilan(10000).toFixed(0));
console.log(soliq);
tsx src/asosiy.ts
12 11200
12
| Yozuv | Ma'nosi |
|---|---|
import { a } from "x" | Nomli import |
import { a as b } from "x" | Qayta nomlash |
import * as n from "x" | Hammasini bitta obyektga |
import d from "x" | Standart import |
Tur importlari #
export type Mahsulot = { nomi: string; narx: number };
export interface Dokon {
nomi: string;
mahsulotlar: Mahsulot[];
}
import type { Mahsulot, Dokon } from "./turlar";
const m: Mahsulot = { nomi: "Olma", narx: 12000 };
const d: Dokon = { nomi: "Dokon", mahsulotlar: [m] };
console.log(d.nomi, d.mahsulotlar[0].narx);
tsx src/asosiy.ts
Dokon 12000
import type nega kerak? Chunki turlar ish vaqtida mavjud
emas. Kompilyatsiyadan keyin nima qolishini ko'ramiz:
export type Mahsulot = { nomi: string; narx: number };
export const QQS = 12;
import type { Mahsulot } from "./turlar";
import { QQS } from "./turlar";
const m: Mahsulot = { nomi: "Olma", narx: 12000 };
console.log(m.nomi, QQS);
tsc
echo "--- dist/asosiy.js ---"
cat dist/asosiy.js
--- dist/asosiy.js ---
import { QQS } from "./turlar";
const m = { nomi: "Olma", narx: 12000 };
console.log(m.nomi, QQS);
import type qatori butunlay yo'qoldi, oddiy import esa
qoldi.
isolatedModules va turni qayta eksport qilish #
Zamonaviy qurish vositalari (esbuild, swc, Vite) har bir faylni
alohida o'giradi - qo'shni fayllarni ochmaydi. Shuning uchun
ular Mahsulot ning tur ekanini bilolmaydi:
export type Mahsulot = { nomi: string; narx: number };
export { Mahsulot } from "./turlar";
tsc --noEmit --isolatedModules 2>&1 | fold -sw 74
src/indeks.ts(1,10): error TS1205: Re-exporting a type when
'isolatedModules' is enabled requires using 'export type'.
export type Mahsulot = { nomi: string; narx: number };
export type { Mahsulot } from "./turlar";
import type { Mahsulot } from "./indeks";
const m: Mahsulot = { nomi: "Olma", narx: 12000 };
console.log(m.narx);
tsc --noEmit --isolatedModules && echo "tsc: xato yo_q"
tsx src/asosiy.ts
tsc: xato yo_q
12000
isolatedModules ni yoqingAgar loyihangiz Vite, esbuild, swc yoki Babel ishlatsa, bu sozlama majburiy deb hisoblang: u kompilyator tekshira oladigan holatda sizni ogohlantiradi.
Aks holda xato qurish vaqtida, tushunarsiz xabar bilan chiqadi.
Kengroq variant - verbatimModuleSyntax: u import/export
qatorlarini o'zgartirmasdan, aynan yozilganicha qoldiradi.
Global soha tuzog'i #
Bu - yangi boshlovchilar eng ko'p duch keladigan chalkashlik:
const nomi = "Olma";
const nomi = "Anor";
tsc --noEmit 2>&1 | fold -sw 74
src/a.ts(1,7): error TS2451: Cannot redeclare block-scoped variable
'nomi'.
src/b.ts(1,7): error TS2451: Cannot redeclare block-scoped variable
'nomi'.
Ikki alohida fayl, bir nomli o'zgaruvchi - va to'qnashuv.
Sabab: birorta import yoki export bo'lmagan .ts fayl
modul emas, skript. Skriptlar global sohani baham ko'radi.
const nomi = "Olma";
console.log(nomi);
export {};
const nomi = "Anor";
console.log(nomi);
export {};
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/a.ts
tsx src/b.ts
tsc: xato yo_q
Olma
Anor
export {} hech narsani eksport qilmaydi - u faqat "bu fayl
modul" deb e'lon qiladi.
Skript rejimi tasodifiy emas - u <script> tegi orqali
yuklanadigan eski JavaScript uchun.
Zamonaviy loyihada esa har bir fayl odatda nimadir eksport qiladi, shuning uchun muammo faqat tajriba fayllarida uchraydi.
tsconfig.json da "moduleDetection": "force" yozsangiz,
TypeScript har bir faylni modul deb hisoblaydi va bu
chalkashlik butunlay yo'qoladi.
Import yo'llari va kengaytma #
Boshida "./narx" deb kengaytmasiz yozdik. Bu har doim ham
ishlamaydi:
export const QQS = 12;
import { QQS } from "./narx";
console.log(QQS);
tsc --noEmit --module nodenext --moduleResolution nodenext 2>&1 | fold -sw 74
src/asosiy.ts(1,21): error TS2835: Relative import paths need explicit
file extensions in ECMAScript imports when '--moduleResolution' is
'node16' or 'nodenext'. Did you mean './narx.js'?
E'tibor bering: ./narx.js, ./narx.ts emas. Fayl .ts,
lekin import ishlaydigan natija .js bo'ladi.
moduleResolution | Yozuv | Qayerda |
|---|---|---|
bundler | "./narx" | Vite, webpack, esbuild |
nodenext | "./narx.js" | Node.js da to'g'ridan-to'g'ri |
node10 (eski) | "./narx" | Eski loyihalar |
Bu darslikda bundler ishlatiladi - 2-bobdagi
tsconfig.json da shunday yozilgan.
Barrel fayl #
Bir papkadagi hamma narsani bitta joydan chiqarish:
export const QQS = 12;
export function qqsBilan(n: number): number {
return n * (1 + QQS / 100);
}
export default class Dokon {
constructor(public nomi: string) {}
}
export * from "./narx";
export { default as Dokon } from "./dokon";
import { QQS, qqsBilan, Dokon } from "./indeks";
const d = new Dokon("Dokon");
console.log(d.nomi, QQS, qqsBilan(10000).toFixed(0));
tsx src/asosiy.ts
Dokon 12 11200
export { default as Dokon } standart eksportni nomli
eksportga aylantirdi.
export * bilan yozilgan katta barrel:
- bitta narsa kerak bo'lsa ham butun papkani yuklaydi;
- doiraviy bog'liqlik ehtimolini oshiradi;
- qurish vaqtini sezilarli uzaytiradi.
Kichik, aniq maqsadli barrel - foydali. Butun loyiha uchun
bitta index.ts esa odatda muammo manbai.
Yuqori darajadagi await #
async function narxi(nomi: string): Promise<number> {
return nomi === "Olma" ? 12000 : 0;
}
const n = await narxi("Olma");
console.log("narx:", n);
export {};
tsx src/asosiy.ts
narx: 12000
await ni async funksiyadan tashqarida ishlatish mumkin -
lekin faqat modulda. Yana bir sabab export {} yozishga.
Doiraviy bog'liqlik #
import { b } from "./b";
export const a = "A";
export function chop(): void {
console.log("a =", a, "| b =", b);
}
import { a } from "./a";
export const b = "B-" + a;
import { chop } from "./a";
chop();
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/asosiy.ts 2>&1 | grep -oE "(a = .*|ReferenceError.*)" | head -1
tsc: xato yo_q
ReferenceError: Cannot access 'a' before initialization
tsc hech qanday xato bermadi - doiraviy import turlar
darajasida mutlaqo qonuniy. Ish vaqtida esa b.ts a ni
o'qimoqchi bo'ldi, lekin a.ts hali a ni yaratmagan edi.
| Nima import qilinadi | Xavf |
|---|---|
import type { X } | Yo'q - kompilyatsiyada yo'qoladi |
| Funksiya (chaqirilguncha) | Kam |
| Modul yuklanishida ishlatiladigan qiymat | Yuqori |
Turlar uchun doira bemalol. Qiymatlar uchun esa bog'liqlikni uchinchi faylga chiqaring.
Xulosa #
- TypeScript ES modullaridan foydalanadi:
exportvaimport. - Bir faylda bitta
defaultva istalgancha nomli eksport bo'ladi; nomli eksport odatda afzal. import * as nhammasini bitta obyektga,asesa qayta nomlashga xizmat qiladi.import typekompilyatsiyadan keyin butunlay yo'qoladi.isolatedModulesyoqilganda turni qayta eksport qilishexport typetalab qiladi (TS1205).import/exportbo'lmagan.tsfayl modul emas, skript - u global sohani baham ko'radi vaTS2451beradi.export {}faylni modulga aylantiradi;"moduleDetection": "force"buni butun loyihada qiladi.moduleResolution: nodenextda import yo'lida.jskengaytmasi yozilishi kerak -.tsemas.- Barrel fayl qulay, lekin katta bo'lsa qurish vaqtini va doiraviy bog'liqlik xavfini oshiradi.
- Yuqori darajadagi
awaitfaqat modulda ishlaydi. - Doiraviy import turlar uchun xavfsiz, qiymatlar uchun ish
vaqtida
ReferenceErrorberadi.
- Ikkita fayl yarating: biri funksiya eksport qilsin, ikkinchisi uni chaqirsin.
- Standart eksport qo'shing va uni boshqa nom bilan import qiling.
import * asbilan butun modulni bitta obyektga oling.- Turlarni alohida faylga chiqarib,
import typebilan oling. tscni ishga tushirib,dist/dagi natijada tur importi yo'qolganini tasdiqlang.--isolatedModulesbilan turni oddiyexportqilib,TS1205ni chaqiring.- Ikkita faylda bir nomli
constyozib,TS2451ni oling. export {}qo'shib tuzating.--moduleResolution nodenextbilan kompilyatsiya qilib,TS2835xabaridagi tavsiyani o'qing.- Doiraviy bog'liqlik yarating va uni uchinchi fayl orqali yeching.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.