11-bo‘lim

Modullar

export va import, tur importlari, barrel fayllar, global soha tuzog'i va doiraviy bog'liqlik.

🕑 28 daqiqa o‘qish 📄 881 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. export va import
  2. Standart eksport
  3. Nom fazosi va qayta nomlash
  4. Tur importlari
  5. isolatedModules va turni qayta eksport qilish
  6. Global soha tuzog'i
  7. Import yo'llari va kengaytma
  8. Barrel fayl
  9. Yuqori darajadagi await
  10. Doiraviy bog'liqlik
  11. Xulosa

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 #

TS
export const QQS = 12;

export function qqsBilan(narx: number): number {
  return narx * (1 + QQS / 100);
}
TS
import { QQS, qqsBilan } from "./narx";

console.log(QQS, qqsBilan(10000).toFixed(0));
Terminal
tsx src/asosiy.ts
Natija
12 11200

Import yo'li - "./narx", fayl nomi esa narx.ts. Kengaytmasiz yozildi; nega bunday ekanini quyida ko'ramiz.

Standart eksport #

TS
export const manzil = "Toshkent";

export default class Dokon {
  constructor(public nomi: string) {}
}
TS
import Dokon, { manzil } from "./dokon";

const d = new Dokon("Husanboy dokoni");
console.log(d.nomi, manzil);
Terminal
tsx src/asosiy.ts
Natija
Husanboy dokoni Toshkent

Bir faylda bitta default va istalgancha nomli eksport bo'lishi mumkin.

Standart eksportdan ehtiyot bo'ling

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 #

TS
export const QQS = 12;
export function qqsBilan(narx: number): number {
  return narx * (1 + QQS / 100);
}
TS
import * as narx from "./narx";
import { QQS as soliq } from "./narx";

console.log(narx.QQS, narx.qqsBilan(10000).toFixed(0));
console.log(soliq);
Terminal
tsx src/asosiy.ts
Natija
12 11200
12
YozuvMa'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 #

TS
export type Mahsulot = { nomi: string; narx: number };

export interface Dokon {
  nomi: string;
  mahsulotlar: Mahsulot[];
}
TS
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);
Terminal
tsx src/asosiy.ts
Natija
Dokon 12000

import type nega kerak? Chunki turlar ish vaqtida mavjud emas. Kompilyatsiyadan keyin nima qolishini ko'ramiz:

TS
export type Mahsulot = { nomi: string; narx: number };
export const QQS = 12;
TS
import type { Mahsulot } from "./turlar";
import { QQS } from "./turlar";

const m: Mahsulot = { nomi: "Olma", narx: 12000 };
console.log(m.nomi, QQS);
Terminal
tsc
echo "--- dist/asosiy.js ---"
cat dist/asosiy.js
Natija
--- 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.

Kompilyatsiyadan keyin nima qoladi asosiy.ts import type { Mahsulot } from "./turlar"; import { QQS } from "./turlar"; const m: Mahsulot = { ... }; console.log(m.nomi, QQS); tsc dist/asosiy.js import { QQS } from "./turlar"; const m = { nomi: "Olma", narx: 12000 }; console.log(m.nomi, QQS); tur bilan bog'liq hamma narsa o'chdi Nega bu muhim: qurish vositalari faylni alohida, qo'shnilarini ko'rmasdan o'giradi. "type" so'zi ularga o'chirish kerakligini aytadi - taxmin qilish shart emas.
import type - qurish vositasiga berilgan aniq ko'rsatma

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:

TS
export type Mahsulot = { nomi: string; narx: number };
TS
export { Mahsulot } from "./turlar";
Terminal
tsc --noEmit --isolatedModules 2>&1 | fold -sw 74
Natija
src/indeks.ts(1,10): error TS1205: Re-exporting a type when
'isolatedModules' is enabled requires using 'export type'.
TS
export type Mahsulot = { nomi: string; narx: number };
TS
export type { Mahsulot } from "./turlar";
TS
import type { Mahsulot } from "./indeks";
const m: Mahsulot = { nomi: "Olma", narx: 12000 };
console.log(m.narx);
Terminal
tsc --noEmit --isolatedModules && echo "tsc: xato yo_q"
tsx src/asosiy.ts
Natija
tsc: xato yo_q
12000
isolatedModules ni yoqing

Agar 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:

TS
const nomi = "Olma";
TS
const nomi = "Anor";
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
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.

TS
const nomi = "Olma";
console.log(nomi);
export {};
TS
const nomi = "Anor";
console.log(nomi);
export {};
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/a.ts
tsx src/b.ts
Natija
tsc: xato yo_q
Olma
Anor

export {} hech narsani eksport qilmaydi - u faqat "bu fayl modul" deb e'lon qiladi.

Bu qoida eski kodda foydali

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:

TS
export const QQS = 12;
TS
import { QQS } from "./narx";
console.log(QQS);
Terminal
tsc --noEmit --module nodenext --moduleResolution nodenext 2>&1 | fold -sw 74
Natija
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.

moduleResolutionYozuvQayerda
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:

TS
export const QQS = 12;
export function qqsBilan(n: number): number {
  return n * (1 + QQS / 100);
}
TS
export default class Dokon {
  constructor(public nomi: string) {}
}
TS
export * from "./narx";
export { default as Dokon } from "./dokon";
TS
import { QQS, qqsBilan, Dokon } from "./indeks";

const d = new Dokon("Dokon");
console.log(d.nomi, QQS, qqsBilan(10000).toFixed(0));
Terminal
tsx src/asosiy.ts
Natija
Dokon 12 11200

export { default as Dokon } standart eksportni nomli eksportga aylantirdi.

Barrel fayl bepul emas

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 #

TS
async function narxi(nomi: string): Promise<number> {
  return nomi === "Olma" ? 12000 : 0;
}

const n = await narxi("Olma");
console.log("narx:", n);
export {};
Terminal
tsx src/asosiy.ts
Natija
narx: 12000

await ni async funksiyadan tashqarida ishlatish mumkin - lekin faqat modulda. Yana bir sabab export {} yozishga.

Doiraviy bog'liqlik #

TS
import { b } from "./b";

export const a = "A";

export function chop(): void {
  console.log("a =", a, "| b =", b);
}
TS
import { a } from "./a";

export const b = "B-" + a;
TS
import { chop } from "./a";
chop();
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/asosiy.ts 2>&1 | grep -oE "(a = .*|ReferenceError.*)" | head -1
Natija
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.

Doiraviy bog'liqlik - turlar bilan xavfsiz, qiymatlar bilan xavfli
Nima import qilinadiXavf
import type { X }Yo'q - kompilyatsiyada yo'qoladi
Funksiya (chaqirilguncha)Kam
Modul yuklanishida ishlatiladigan qiymatYuqori

Turlar uchun doira bemalol. Qiymatlar uchun esa bog'liqlikni uchinchi faylga chiqaring.

Xulosa #

  • TypeScript ES modullaridan foydalanadi: export va import.
  • Bir faylda bitta default va istalgancha nomli eksport bo'ladi; nomli eksport odatda afzal.
  • import * as n hammasini bitta obyektga, as esa qayta nomlashga xizmat qiladi.
  • import type kompilyatsiyadan keyin butunlay yo'qoladi.
  • isolatedModules yoqilganda turni qayta eksport qilish export type talab qiladi (TS1205).
  • import/export bo'lmagan .ts fayl modul emas, skript - u global sohani baham ko'radi va TS2451 beradi.
  • export {} faylni modulga aylantiradi; "moduleDetection": "force" buni butun loyihada qiladi.
  • moduleResolution: nodenext da import yo'lida .js kengaytmasi yozilishi kerak - .ts emas.
  • Barrel fayl qulay, lekin katta bo'lsa qurish vaqtini va doiraviy bog'liqlik xavfini oshiradi.
  • Yuqori darajadagi await faqat modulda ishlaydi.
  • Doiraviy import turlar uchun xavfsiz, qiymatlar uchun ish vaqtida ReferenceError beradi.
Amaliy topshiriq
  1. Ikkita fayl yarating: biri funksiya eksport qilsin, ikkinchisi uni chaqirsin.
  2. Standart eksport qo'shing va uni boshqa nom bilan import qiling.
  3. import * as bilan butun modulni bitta obyektga oling.
  4. Turlarni alohida faylga chiqarib, import type bilan oling.
  5. tsc ni ishga tushirib, dist/ dagi natijada tur importi yo'qolganini tasdiqlang.
  6. --isolatedModules bilan turni oddiy export qilib, TS1205 ni chaqiring.
  7. Ikkita faylda bir nomli const yozib, TS2451 ni oling.
  8. export {} qo'shib tuzating.
  9. --moduleResolution nodenext bilan kompilyatsiya qilib, TS2835 xabaridagi tavsiyani o'qing.
  10. Doiraviy bog'liqlik yarating va uni uchinchi fayl orqali yeching.

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.