Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. import type va export type
- 2.1 Uch yozuv
- 2.2 import type va import { type … } farqi
- 3. verbatimModuleSyntax va isolatedModules
- 3.1 verbatimModuleSyntax — "yozilganini aynan qoldir"
- 3.2 isolatedModules — yengilroq qarindoshi
- 3.3 erasableSyntaxOnly — faqat o'chirib bo'ladigan sintaksis
- 3.4 Nega JavaScript'da bu muammo yo'q edi?
- 3.5 Skript yoki modul: export {}
- 3.6 Dinamik import() va uning turi
- 4. .ts kengaytmali importlar
- 4.1 Ikki dunyo
- 4.2 Ikki bayroq
- 5. paths taxalluslari va TypeScript ushlamaydigan tuzoq
- 5.1 paths — faqat tekshiruv uchun
- 5.2 Node uchun: package.json dagi imports
- 6. ESM va CommonJS: .mts va .cts
- 7. Ko'p uchraydigan xatolar
- 7.1 Turni oddiy import qilish
- 7.2 Turni type siz qayta eksport
- 7.3 Build'da .ts import
- 7.4 paths ga Node'da ishonish
- 7.5 import x = require()
- 8. Mashqlar
- 1-mashq (oson): Nima qoladi?
- 2-mashq (o'rta): Taxallusni tuzating
- 3-mashq (qiyin): Amaliy tajriba — modulning "old eshigi"
- 9. Real ishda
- Xulosa
- Manbalar
TypeScript modullari: import type, verbatimModuleSyntax va .ts kengaytmali importlar
Qisqacha: TypeScript turlari JavaScript'ga o'tmaydi — shuning uchun faqat tur bo'lgan importni
import typedeb belgilash kerak. Aks holda turlarni o'chiradigan vositalar (Node, esbuild) uni oddiy import deb qoldiradi va ishlash paytidadoes not provide an export namedxatosi chiqadi.verbatimModuleSyntaxbuni kompilyatsiyada ushlaydi. Node.tsni o'zi ishga tushirganda importda"./menu.ts"yoziladi, build paytida esarewriteRelativeImportExtensionsuni"./menu.js"ga almashtiradi.
Bu darsda
import type,import { type X }vaexport typeni ishlatasiz va ular.jsda nima qoldirishini bilasiz.verbatimModuleSyntaxvaisolatedModulesnima uchun kerakligini — "har fayl alohida" tamoyilini — tushuntirasiz..tskengaytmali importlar varewriteRelativeImportExtensionsbilan build'ni sozlaysiz.pathstaxalluslari nega Node'da ishlamasligini va o'rnigapackage.jsondagiimportsni ishlatasiz..mts/.ctsva CommonJS bilan TypeScript qanday ishlashini bilasiz.
Oldin bilishingiz kerak: Strict bayroqlar oilasi, tsconfig.json chuqur, ESM import, CommonJS va ESM.
1. Nega bu kerak?
O'tgan darsda qat'iy bayroqlarni ko'rdik. Endi modullar — fayllar orasidagi aloqa. TypeScript'da bitta yangi muammo bor: importning ba'zilari qiymat (funksiya, massiv), ba'zilari esa faqat tur. Turlar ishlash paytida yo'q. Bu oddiy faktdan butun bir dars kelib chiqadi.
«Bahor» loyihasida Sardor turlarni alohida faylga chiqardi:
// types.ts
export type MenuItem = { name: string; price: number };// main.ts
import { MenuItem } from "./types.ts";
const osh: MenuItem = { name: "Osh", price: 35000 };
console.log(osh.name);npx tsc — xatosiz (sozlamada verbatimModuleSyntax yo'q). Sardor node main.ts ni ishga tushirdi (TypeScript'ni o'rnatish darsidagi Node type stripping). Natija:
import { MenuItem } from "./types.ts";
^^^^^^^^
SyntaxError: The requested module './types.ts' does not provide an export named 'MenuItem'"So'ralgan ./types.ts moduli MenuItem degan eksportni bermaydi". Nima bo'ldi? Node .ts fayldan turlarni o'chiradi. types.ts dagi export type MenuItem — butunlay o'chdi, fayl bo'sh qoldi. main.ts dagi import { MenuItem } esa oddiy import ko'rinishida — Node bilmaydi, MenuItem tur yoki qiymat. U importni qoldirdi va bo'sh moduldan MenuItem ni so'radi.
tsc buni bilardi — u ikkala faylni ham ko'radi. Node esa (va esbuild, SWC kabi tezkor vositalar ham) har faylni alohida o'qiydi va qo'shni faylga qaramaydi. Yechim — importning o'zida "bu faqat tur" deb yozish.
2. import type va export type
2.1 Uch yozuv
import type { MenuItem } from "./types.ts"; // 1
import { type MenuItem, MENU } from "./menu.ts"; // 2
export type { MenuItem } from "./types.ts"; // 3| Yozuv | Ma'nosi | .js da nima qoladi |
|---|---|---|
import type { X } |
butun import — faqat turlar | hech narsa — qator o'chadi |
import { type X, y } |
X — tur, y — qiymat |
import { y } |
export type { X } |
tur sifatida qayta eksport | hech narsa |
Sardorning tuzatilgan kodi:
// main.ts
import type { MenuItem } from "./types.ts";
const osh: MenuItem = { name: "Osh", price: 35000 };
console.log(osh.name);Endi Node ham, tsc ham import type qatorini butunlay o'chiradi — types.ts umuman yuklanmaydi.
2.2 import type va import { type … } farqi
Mayda, lekin muhim farq. tsc (verbatimModuleSyntax bilan) ikki xil importni shunday chiqardi:
import type { MenuItem } from "./lib/menu.ts";
import { type MenuItem as Item } from "./lib/menu.ts";import {} from "./lib/menu.js";Birinchi qator butunlay yo'qoldi. Ikkinchisidan import {} from "./lib/menu.js" qoldi: { } ichi bo'sh, lekin modul baribir yuklanadi va undagi kod bajariladi. Qoida: hamma import qilinadiganlar tur bo'lsa — import type; aralash bo'lsa — import { type X, y }.
Tekshirib ko'ring:
menu.tsdaconsole.log("menyu yuklandi")qatori bor.import { type MenuItem } from "./menu.ts"yozilgan faylni ishga tushirsangiz, bu yozuv chiqadimi?import type { MenuItem }bilan-chi?
Javob
Birinchisida — chiqadi: import {} from "./menu.js" modulni yuklaydi va uning kodi bajariladi. Ikkinchisida — chiqmaydi: qator butunlay o'chadi. Ko'pincha farqi yo'q, lekin modul "yon ta'sirli" bo'lsa (yuklanganda nimadir qiladi) — muhim.
3. verbatimModuleSyntax va isolatedModules
3.1 verbatimModuleSyntax — "yozilganini aynan qoldir"
verbatimModuleSyntax ("so'zma-so'z modul sintaksisi") — qoida: type deb belgilanmagan har bir import va eksport .js da aynan qoladi. Shuning uchun tsc tur bo'lgan, lekin type siz importni xato deb ko'rsatadi:
// @ts-options: {"verbatimModuleSyntax": true}
import { PathLike, existsSync } from "node:fs";
const file: PathLike = "menu.json";
console.log(existsSync(file));Kompilyator:
TS1484: 'PathLike' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.Tarjimasi: "PathLike — tur, verbatimModuleSyntax yoqilganda uni faqat-tur importi bilan olish kerak". PathLike — Node turlaridagi "fayl yo'li" turi (@types/node dan); existsSync — haqiqiy funksiya. Tuzatilgani:
// @ts-options: {"verbatimModuleSyntax": true}
import { type PathLike, existsSync } from "node:fs";
const file: PathLike = "menu-yoq.json";
console.log(existsSync(file)); // falseQayta eksportda ham xuddi shunday — TS1205: Re-exporting a type when 'verbatimModuleSyntax' is enabled requires using 'export type'. («Ko'p uchraydigan xatolar» va mashqda haqiqiy chiqishi bor).
verbatimModuleSyntax siz TypeScript importni o'zi "tozalardi": turga ishlatilgan importni jim o'chirib yuborardi. Bu tsc uchun ishlaydi, lekin Node va bundler'lar buni qila olmaydi — ular faylni yolg'iz ko'radi. Bayroq hamma vositalar bir xil natija berishini kafolatlaydi. tsc --init (TypeScript 7.0.2) uni yoqib qo'yadi; mashqlar papkamizda va vazifalar da ham yoqiq.
3.2 isolatedModules — yengilroq qarindoshi
isolatedModules — "har fayl alohida tarjima qilinishi mumkin bo'lsin". U faqat yolg'iz faylda hal qilib bo'lmaydigan holatlarni taqiqlaydi: masalan, turni type siz qayta eksport qilish (TS1205 — xuddi shu xabar, faqat 'isolatedModules' is enabled). import { MenuItem } ni esa o'tkazadi — chunki tsc uni o'zi o'chira oladi.
isolatedModules |
verbatimModuleSyntax |
|
|---|---|---|
export { MenuItem } from … (tur) |
TS1205 |
TS1205 |
import { MenuItem } (tur) |
o'tadi | TS1484 |
| Natija | bundler'lar bilan xavfsiz | hamma vosita bilan aynan bir xil |
verbatimModuleSyntax — qat'iyroq va soddaroq qoida ("yozilgani qoladi"), isolatedModules ning hamma tekshiruvlarini o'z ichiga oladi. Yangi loyihalarda shu tanlanadi.
3.3 erasableSyntaxOnly — faqat o'chirib bo'ladigan sintaksis
Node turlarni o'chiradi, lekin TypeScript'ning ba'zi yozuvlarini JavaScript'ga o'girish kerak — ularni o'chirib bo'lmaydi: enum, qiymatli namespace, klass parametr xususiyatlari (enum va muqobillari, Klasslar) va eski CommonJS importi:
// @ts-options: {"erasableSyntaxOnly": true}
import fs = require("node:fs");Kompilyator:
TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled."erasableSyntaxOnly yoqilganda bu sintaksisga ruxsat yo'q". import x = require(…) — TypeScript'ning o'z yozuvi, uni o'chirib emas, const x = require(…) ga aylantirib bo'ladi. Bayroq Node to'g'ridan-to'g'ri ishga tushira oladigan kodni kafolatlaydi.
3.4 Nega JavaScript'da bu muammo yo'q edi?
JavaScript'da har bir eksport — qiymat: funksiya, massiv, son. Import qilingan nom ishlash paytida doim mavjud. TypeScript esa ikkinchi "qavat" qo'shdi — faqat kompilyatsiyada yashaydigan nomlar. Bir fayl ichida bu muammo emas: tur va qiymat yonma-yon, tsc ularni ajrata oladi. Muammo fayllar chegarasida paydo bo'ladi: import qatoriga qarab, nom qaysi qavatdan ekanini bilib bo'lmaydi.
import type — shu chegarani ko'rinadigan qiladi. Kod o'quvchisi ham qatorga qarab biladi: "bu fayldan faqat turlar olinyapti, ishlash paytida u yuklanmaydi". Bu modullar orasidagi bog'liqlikni tushunishni ham osonlashtiradi: import type — "yumshoq" bog'liqlik, oddiy import — "qattiq" (fayl yuklanadi, kodi bajariladi).
3.5 Skript yoki modul: export {}
Tur annotatsiyasi darsida tsc chiqishining oxirida export {}; qatorini ko'rgan edik. U nima? TypeScript har faylni ikki xildan biri deb biladi:
- modul — faylda
importyokiexportbor: undagi nomlar faqat shu faylniki; - skript — ikkalasi ham yo'q: undagi nomlar global, boshqa fayllar bilan bitta maydonda.
Ikki skript faylda bir xil nom bo'lsa, ular to'qnashadi. a.ts va b.ts — ikkalasida const total = …, import/export yo'q. Sozlamasiz npx tsc --ignoreConfig --noEmit a.ts b.ts:
a.ts(1,7): error TS2451: Cannot redeclare block-scoped variable 'total'.
b.ts(1,7): error TS2451: Cannot redeclare block-scoped variable 'total'.TypeScript aytyapti: "total blok o'zgaruvchisini qayta e'lon qilib bo'lmaydi" — ikki fayl bitta global maydonni bo'lishyapti. Yechim — faylni modul qilish. tsc --init yozgan "moduleDetection": "force" aynan shuni qiladi: har fayl — modul, import bo'lmasa ham. Shunda tsc chiqishga export {}; qo'shadi — "bu fayl modul" degan belgi, JavaScript'da ham fayl modul bo'lib qolsin. Skript kerak bo'lgan kam holatlar ham bor: global turlarni e'lon qiladigan .d.ts (keyingi dars) va <script> bilan ulanadigan oddiy skript (vazifalar dagi tema.js).
3.6 Dinamik import() va uning turi
Dinamik import() — modulni kerak bo'lganda yuklash. Uning turini yozish uchun maxsus yozuv bor — typeof import("…"):
// 35-modullar/lazy.ts — menyu moduli faqat kerak bo'lganda
type MenuModule = typeof import("./menu.ts");
export async function loadPrice(dish: string): Promise<number> {
const menu: MenuModule = await import("./menu.ts");
return menu.priceOf(dish);
}typeof import("./menu.ts") — "shu modul eksportlarining turi": { MENU: …; priceOf: (dish: string) => number }. Bu qator ham faqat tur — menu.ts ni oldindan yuklamaydi. Biz sinadik: npx tsc — toza, await loadPrice("Osh") — 35000. vazifalar da ham shunday: asosiy.ts o'lchov modulini import("./olchov.ts") bilan, sahifa yuklangandan keyin oladi.
4. .ts kengaytmali importlar
4.1 Ikki dunyo
tsconfig.json chuqur darsining mashqida bitta loyihada ikki xil import bor edi: test "./shifts.ts" ni, main.ts esa "./shifts.js" ni import qilardi. Sababi:
| Kim ishga tushiradi | Diskdagi fayl | Importda |
|---|---|---|
Node, .ts dan to'g'ridan-to'g'ri |
shifts.ts |
"./shifts.ts" |
Node, build natijasidan (dist/) |
shifts.js |
"./shifts.js" |
tsc importdagi yo'lni standart holatda o'zgartirmaydi. Shuning uchun avval TypeScript'da .js deb yozish odat edi ("kelajakdagi faylga ishora"): manbada .js fayl yo'q, lekin build'dan keyin paydo bo'ladi, tsc esa "./menu.js" ni ko'rib, yonidagi menu.ts ni topadi. Node type stripping bilan esa .ts dan ishga tushirganda .js fayl umuman yo'q — "./menu.js" importi ERR_MODULE_NOT_FOUND beradi. Node faylni "taxmin qilmaydi": importda qaysi nom yozilgan bo'lsa, diskdan aynan shuni qidiradi.
4.2 Ikki bayroq
allowImportingTsExtensions—"./menu.ts"yozishga ruxsat. Lekin faqat.jsyozilmaganda:noEmit(mashqlar papkamiz) yokiemitDeclarationOnlybilan. Usiz — o'rnatish darsidagiTS5097.rewriteRelativeImportExtensions(TypeScript 5.7 dan) —"./menu.ts"deb yozing,tscbuild paytida"./menu.js"ga almashtiradi.
Build qiladigan loyihada allowImportingTsExtensions ni yoqib ko'rdik:
tsconfig.json(7,35): error TS5096: Option 'allowImportingTsExtensions' can only be used when one of 'noEmit', 'emitDeclarationOnly', or 'rewriteRelativeImportExtensions' is set."allowImportingTsExtensions faqat noEmit, emitDeclarationOnly yoki rewriteRelativeImportExtensions bilan ishlatiladi". Build bo'lsa — ikkinchi bayroq kerak. rewriteRelativeImportExtensions bilan manba:
// src/main.ts
import type { MenuItem } from "./lib/menu.ts";
import { MENU } from "./lib/menu.ts";
const first: MenuItem | undefined = MENU[0];
console.log(first?.name);tsc natijasi (dist/main.js):
import { MENU } from "./lib/menu.js";
const first = MENU[0];
console.log(first?.name);Ikki narsa bo'ldi: import type qatori o'chdi, .ts — .js ga almashdi. node src/main.ts ham, node dist/main.js ham Osh chiqardi. Bitta yo'l — ikki muhit.
flowchart LR
A["src/main.ts: import ./menu.ts"] --> B["node src/main.ts"]
A --> C["tsc + rewriteRelativeImportExtensions"]
C --> D["dist/main.js: import ./menu.js"]
D --> E["node dist/main.js"]
B --> F["Osh"]
E --> Fvazifalar aynan shunday: testlar Node'da .ts dan ishlaydi, brauzer dist/ dagi .js ni oladi, importlar — "./sinxron.ts" (Discriminated union qadamidan beri).
Tekshirib ko'ring:
rewriteRelativeImportExtensionsimport { x } from "lodash.ts"ni ham o'zgartiradimi?
Javob
Yo'q. Bayroq nomida "relative" bor — faqat nisbiy yo'llar (./, ../ bilan boshlanadigan) almashtiriladi. Paket nomlari ("lodash", "node:fs") o'zgarmaydi — ular .ts fayl emas.
5. paths taxalluslari va TypeScript ushlamaydigan tuzoq
5.1 paths — faqat tekshiruv uchun
Katta loyihada "../../../lib/menu.ts" kabi uzun yo'llar paydo bo'ladi. paths — qisqa taxallus:
{
"compilerOptions": {
"paths": { "@/*": ["./src/*"] }
}
}Endi import { MENU } from "@/lib/menu.js" — tsc uni src/lib/menu.ts ga topadi va tekshiradi. Lekin build natijasi:
import { MENU } from "@/lib/menu.js";
console.log(MENU.length);tsc yo'lni o'zgartirmadi — paths faqat tur tekshiruvi uchun. Node esa:
Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@/lib' imported from …\dist\main.js"@/lib paketi topilmadi". Node @/ ni npm paketi deb o'yladi. Bu — darsning "TypeScript ushlamaydigan" tuzog'i: tsc toza, dastur esa ishga tushmaydi. Vite kabi bundler'lar paths ni o'zlari tushunadi (16-qism), Node esa — yo'q.
5.2 Node uchun: package.json dagi imports
Node'ning o'z taxallus mexanizmi bor — package.json dagi imports maydoni. Nomlar # bilan boshlanadi:
{
"type": "module",
"imports": { "#lib/*": "./src/lib/*" }
}// src/main.ts
import { MENU } from "#lib/menu.ts";
console.log(MENU.length);module: nodenext dagi tsc ham, Node ham imports ni biladi: npx tsc — toza, node src/main.ts — 1. Bitta taxallus, ikki vosita bir xil tushunadi. paths dan farqi — u standart, Node'ning o'zida.
6. ESM va CommonJS: .mts va .cts
CommonJS va ESM darsidan bilasiz: Node'da ikki modul tizimi bor. module: nodenext da TypeScript fayl turini Node kabi aniqlaydi:
| Fayl | Modul tizimi | Build natijasi |
|---|---|---|
.ts |
package.json dagi "type" ga qarab |
.js |
.mts |
doim ESM | .mjs |
.cts |
doim CommonJS | .cjs |
O'tgan darsda ko'rdik: bir xil .ts "type": "module" bilan ESM, usiz — CommonJS (require, exports) bo'lib chiqdi. ESM loyihada bitta CommonJS fayl kerak bo'lsa (masalan, eski vosita sozlamasi) — uni .cts deb nomlang. Ichida const fs = require("node:fs") va module.exports — oddiy CommonJS. TypeScript'ning eski import fs = require() va export = yozuvlari esa erasableSyntaxOnly bilan taqiqlangan — ularni yangi kodda yozmang.
7. Ko'p uchraydigan xatolar
7.1 Turni oddiy import qilish
SyntaxError: The requested module './types.ts' does not provide an export named 'MenuItem' (Node) yoki TS1484 (verbatimModuleSyntax bilan). Tuzatish: import type { MenuItem }.
7.2 Turni type siz qayta eksport
TS1205: Re-exporting a type when 'verbatimModuleSyntax' is enabled requires using 'export type'. Tuzatish: export type { MenuItem } from "./types.ts".
7.3 Build'da .ts import
TS5097 yoki TS5096. Tuzatish: rewriteRelativeImportExtensions (build) yoki noEmit + allowImportingTsExtensions (faqat tekshiruv).
7.4 paths ga Node'da ishonish
ERR_MODULE_NOT_FOUND: Cannot find package '@/lib'. Tuzatish: package.json imports (#lib/*) yoki bundler.
7.5 import x = require()
TS1294 (erasableSyntaxOnly). Tuzatish: ESM'da — import fs from "node:fs"; CommonJS'da (.cts) — const fs = require("node:fs").
8. Mashqlar
1-mashq (oson): Nima qoladi?
verbatimModuleSyntax yoqilgan. Har qatordan .js da nima qoladi?
import type { MenuItem } from "./types.ts";— qator qoladimi (ha/yo'q)?import { type MenuItem, MENU } from "./menu.ts";— qaysi nom qoladi?export type { OrderLine } from "./types.ts";— qoladimi?
Yechim
import type va export type — butunlay o'chadi. Aralash importdan faqat qiymat qoladi: import { MENU } from "./menu.js" (build'da rewriteRelativeImportExtensions bilan .js).
2-mashq (o'rta): Taxallusni tuzating
Loyiha build qilinmaydi — Node .ts ni to'g'ridan-to'g'ri ishga tushiradi. tsconfig.json da "paths": { "@lib/*": ["./src/lib/*"] } bor va import { MENU } from "@lib/menu.ts" yozilgan. tsc toza, node src/main.ts esa ERR_MODULE_NOT_FOUND. Nima o'zgartirasiz?
Yechim
paths ni olib tashlab, package.json ga imports qo'shamiz va taxallusni # bilan boshlaymiz:
{
"type": "module",
"imports": { "#lib/*": "./src/lib/*" }
}Importda: import { MENU } from "#lib/menu.ts". tsconfig.json da module: nodenext (u imports ni o'qiydi) va allowImportingTsExtensions + noEmit. Biz shu sozlamani sinadik: npx tsc — toza, node src/main.ts — 1. # majburiy — Node imports nomlarini shu belgidan taniydi va ularni npm paketlari bilan adashtirmaydi.
3-mashq (qiyin): Amaliy tajriba — modulning "old eshigi"
kurs/mashqlar/15/35-modullar/ da (umumiy tsconfig.json — verbatimModuleSyntax va allowImportingTsExtensions yoqiq) to'rt fayl yarating:
types.ts— faqat turlar:MenuItem(name,price),OrderLine(dish,qty).menu.ts—MENU(osh, lag'mon, ko'k choy) vapriceOf(dish)(yo'q taom —RangeError).order.ts—orderTotal(lines).index.ts— barrel ("old eshik"): qolgan uchta fayldan kerakli hamma narsani qayta eksport qiladi. Boshqa kod faqat./index.tsdan import qiladi.
Avval order.ts da import { OrderLine } va index.ts da export { MenuItem, OrderLine } from "./types.ts" deb (type siz) yozing. npx tsc --pretty false ni, keyin node --test 35-modullar/index.test.ts ni ishga tushiring.
Yechim
type siz variantda tsc uchta xato berdi:
35-modullar/index.ts(4,10): error TS1205: Re-exporting a type when 'verbatimModuleSyntax' is enabled requires using 'export type'.
35-modullar/index.ts(4,20): error TS1205: Re-exporting a type when 'verbatimModuleSyntax' is enabled requires using 'export type'.
35-modullar/order.ts(2,10): error TS1484: 'OrderLine' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.Node esa tsc ni kutmaydi — testni baribir ishga tushiradi va yiqiladi:
SyntaxError: The requested module './types.ts' does not provide an export named 'OrderLine'
✖ 35-modullar\index.test.ts (228.7554ms)«Nega bu kerak?» bo'limidagi xatoning o'zi. Shuning uchun ish tartibi: avval npx tsc, keyin testlar.
// 35-modullar/types.ts — faqat turlar (JS'da bo'sh modul)
export type MenuItem = {
readonly name: string;
readonly price: number;
};
export type OrderLine = {
readonly dish: string;
readonly qty: number;
};// 35-modullar/menu.ts — menyu va narx
import type { MenuItem } from "./types.ts";
export const MENU: readonly MenuItem[] = [
{ name: "Osh", price: 35000 },
{ name: "Lag'mon", price: 28000 },
{ name: "Ko'k choy", price: 5000 },
];
export function priceOf(dish: string): number {
const item = MENU.find((m) => m.name === dish);
if (item === undefined) {
throw new RangeError(`Menyuda yo'q: ${dish}`);
}
return item.price;
}// 35-modullar/order.ts — buyurtma summasi
import type { OrderLine } from "./types.ts";
import { priceOf } from "./menu.ts";
export function orderTotal(lines: readonly OrderLine[]): number {
let sum = 0;
for (const line of lines) {
sum += priceOf(line.dish) * line.qty;
}
return sum;
}// 35-modullar/index.ts — modulning "old eshigi"
export { MENU, priceOf } from "./menu.ts";
export { orderTotal } from "./order.ts";
export type { MenuItem, OrderLine } from "./types.ts";// 35-modullar/index.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { MENU, orderTotal, priceOf } from "./index.ts";
import type { OrderLine } from "./index.ts";
test("priceOf: menyudagi narx", () => {
assert.equal(priceOf("Lag'mon"), 28000);
assert.throws(() => priceOf("Pizza"), RangeError);
});
test("orderTotal: 2 osh va 2 choy", () => {
const lines: OrderLine[] = [
{ dish: "Osh", qty: 2 },
{ dish: "Ko'k choy", qty: 2 },
];
assert.equal(orderTotal(lines), 80000);
assert.equal(MENU.length, 3);
});npx tsc --pretty false — chiqishsiz. node --test 35-modullar/index.test.ts bizda (Node 24.21.0):
✔ priceOf: menyudagi narx (3.8043ms)
✔ orderTotal: 2 osh va 2 choy (0.641ms)
ℹ tests 2
ℹ suites 0
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 366.3781Barrel foydasi: menu.ts ni ikkiga bo'lsangiz yoki types.ts ni ko'chirsangiz, faqat index.ts o'zgaradi — tashqi kod ./index.ts dan import qilishda davom etadi. Narxi: katta barrel'lar bundler'ni sekinlashtirishi mumkin (keraksiz modullar ham yuklanadi) — buni 16-qismda ko'ramiz.
XATOLAR.md ga qo'shing: TS1484, TS1205, TS1294, TS5096 va Node'ning does not provide an export named xatosi (TypeScript emas, lekin sababi — tur importi). Keyin kurs/mashqlar papkasidan:
git add 15/35-modullar 15/XATOLAR.md
git commit -m "15/35: barrel modul — import type va export type"9. Real ishda
import type— zamonaviy TypeScript kodining standart qismi: ESLint'da@typescript-eslint/consistent-type-importsqoidasi uni avtomatik talab qiladi, muharrir esa "Add import" da o'zitypeqo'shadi.- Node type stripping va tezkor vositalar (esbuild, SWC, Vite — 16-qism) faylni alohida o'qiydi. Ular bilan ishlaydigan har loyihada
verbatimModuleSyntaxyoki kamidaisolatedModulesyoqiladi. vazifalar—verbatimModuleSyntax,rewriteRelativeImportExtensions,erasableSyntaxOnly: testlar build'siz.tsdan, brauzer —dist/dan.- Taxalluslar: frontend'da
@/(Vite/Next.jspathsni biladi), Node backend'da —package.jsonimports(#…). - Intervyu: "
import typenega kerak?", "isolatedModulesnima?", "pathsnega Node'da ishlamaydi?" — amaliy savollar.
Xulosa
- Turlar ishlash paytida yo'q: faqat tur importi —
import type/import { type X }, qayta eksport —export type. verbatimModuleSyntax—typesiz import aynan qoladi, tur bo'lsa —TS1484/TS1205. Node va bundler'lar bilan natija bir xil bo'ladi.erasableSyntaxOnly— faqat o'chirib bo'ladigan sintaksis (enum,import = requireyo'q).- Node
.tsdan:"./menu.ts"+allowImportingTsExtensions(noEmit); build bilan:rewriteRelativeImportExtensionsuni.jsga almashtiradi. pathsfaqat tekshiruv uchun — Node'dapackage.jsonimports(#lib/*).
Keyingi dars: Declaration fayllari (.d.ts) — kodsiz, faqat turlardan iborat fayllar: declare, declare module, declare global va tsc --declaration.
Manbalar
- TypeScript Handbook: "Modules — Reference" (
verbatimModuleSyntax,isolatedModules) — typescriptlang.org/docs/handbook/modules/reference.html - TSConfig:
verbatimModuleSyntax,rewriteRelativeImportExtensions,allowImportingTsExtensions,erasableSyntaxOnly,paths— typescriptlang.org/tsconfig - TypeScript Release Notes 5.0 (
verbatimModuleSyntax), 5.7 (rewriteRelativeImportExtensions), 5.8 (erasableSyntaxOnly) — typescriptlang.org/docs/handbook/release-notes/ - Node.js hujjatlari: "Modules: Packages — Subpath imports" (
imports) — nodejs.org/api/packages.html#subpath-imports
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!