16-bo‘lim

Tashqi kutubxonalar va @types

Turlar qayerdan keladi, .d.ts yozish, modul va global kengaytirish, ikki bosqichli tasdiqlash.

🕑 25 daqiqa o‘qish 📄 737 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Turlari o'zi bilan keladigan paket
  2. Turlanmagan modul
  3. .d.ts fayl yozish
  4. Tashqi paket uchun e'lon
  5. Modul kengaytirish
  6. Global kengaytirish
  7. Ikki bosqichli tasdiqlash
  8. Xulosa

Haqiqiy loyihada kodning katta qismi sizniki emas - node_modules ichida yotadi. TypeScript ular haqida qayerdan biladi?

Uch yo'l bor, va har biri uchun o'z hal qilish usuli.

Turlari o'zi bilan keladigan paket #

TS
import { readFileSync } from "node:fs";

const matn: string = readFileSync("/etc/hostname", "utf8");
console.log(matn.trim().length > 0);
Terminal
tsx src/fs.ts
Natija
true

Noto'g'ri ishlatilsa darhol tutiladi:

TS
import { readFileSync } from "node:fs";

const matn: number = readFileSync("/etc/hostname", "utf8");
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/fs2.ts(3,7): error TS2322: Type 'string' is not assignable to type
'number'.

Bu bilim @types/node paketidan keladi:

Terminal
ls /ish/node_modules/@types/
echo "--- @types/node hajmi ---"
du -sh /ish/node_modules/@types/node | cut -f1
echo "--- fs e'loni ---"
head -4 /ish/node_modules/@types/node/fs.d.ts
Natija
node
--- @types/node hajmi ---
2.4M
--- fs e'loni ---
/**
 * The `node:fs` module enables interacting with the file system in a
 * way modeled on standard POSIX functions.
 *

2.4 megabayt - faqat turlar uchun. Ular kompilyatsiyadan keyin hech qanday kod qoldirmaydi.

Turlar qayerdan qidiriladi
ManbaMisolQanday topiladi
Paketning o'zidazod, tsxpackage.json dagi types
@types/*@types/nodeAvtomatik, node_modules/@types
Sizning faylingizsrc/*.d.tsinclude ichida bo'lsa

Birinchisi eng yaxshi: kutubxona va uning turlari birga yangilanadi. @types/* esa alohida jamoa tomonidan yuritiladi (DefinitelyTyped loyihasi), shuning uchun ba'zan kutubxona versiyasidan orqada qoladi.

Turlanmagan modul #

JavaScript
export function salom(ism) {
  return "Salom, " + ism + "!";
}
TS
import { salom } from "./eski";
console.log(salom("Husanboy"));
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/asosiy.ts(1,23): error TS7016: Could not find a declaration file for
module './eski'. '/ish/dars/src/eski.js' implicitly has an 'any' type.

TS7016 - "turlarni topa olmadim". Bu xato noImplicitAny tufayli chiqadi.

Eng oson yo'l - allowJs:

JavaScript
export function salom(ism) {
  return "Salom, " + ism + "!";
}
TS
import { salom } from "./eski";
console.log(salom("Husanboy"));
console.log(salom(42));
Terminal
tsc --noEmit --allowJs && echo "tsc: xato yo_q"
tsx src/asosiy.ts
Natija
tsc: xato yo_q
Salom, Husanboy!
Salom, 42!

Ishladi - lekin salom(42) ham o'tdi. allowJs faylni qo'shadi, tekshiruvni esa kuchaytirmaydi.

.d.ts fayl yozish #

JavaScript
export function salom(ism) {
  return "Salom, " + ism + "!";
}
TS
export declare function salom(ism: string): string;
TS
import { salom } from "./eski";
console.log(salom("Husanboy"));
console.log(salom(42));
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/asosiy.ts(3,19): error TS2345: Argument of type 'number' is not
assignable to parameter of type 'string'.

.d.ts - faqat e'lonlar fayli. Unda hech qanday bajariladigan kod yo'q, faqat "bu modulda nima bor" degan tavsif.

declare kalit so'zi "amalga oshirish boshqa joyda" degani.

Tashqi paket uchun e'lon #

Paketning o'zida ham, @types da ham turlar bo'lmasa, o'zingiz e'lon qilasiz:

TS
declare module "sodda-dokon" {
  export function narxla(nomi: string): number;
  export const QQS: number;
}
TS
import { narxla, QQS } from "sodda-dokon";

const n: number = narxla("Olma");
console.log(n + QQS);
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
echo "--- ishga tushirsak ---"
tsx src/asosiy.ts 2>&1 | grep -o "ERR_MODULE_NOT_FOUND" | head -1
Natija
tsc: xato yo_q
--- ishga tushirsak ---
ERR_MODULE_NOT_FOUND

Bu - juda muhim natija. sodda-dokon degan paket umuman mavjud emas, lekin tsc hech narsa demadi.

declare module - 7-bobdagi tur predikati kabi va'da. Kompilyator uni tekshirmaydi.

Shu bilan birga, e'lon ichidagi qoidalar ishlaydi:

TS
declare module "sodda-dokon" {
  export function narxla(nomi: string): number;
}
TS
import { narxla } from "sodda-dokon";
const n: string = narxla(12000);
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/asosiy.ts(2,7): error TS2322: Type 'number' is not assignable to type
'string'.
src/asosiy.ts(2,26): error TS2345: Argument of type 'number' is not
assignable to parameter of type 'string'.
Paket uchun turlarni topish tartibi 1. Paketning o'zida package.json dagi "types" yoki "exports" - kutubxona bilan birga yangilanadi eng yaxshi 2. @types/<nomi> DefinitelyTyped jamoasi yuritadi - versiyadan orqada qolishi mumkin yaxshi 3. O'zingizning .d.ts faylingiz declare module "..." - faqat kerakli qismini yozasiz, tekshirilmaydi ishlaydi 4. declare module "..."; - bo'sh e'lon Butun modul any bo'ladi - TS7016 yo'qoladi, himoya ham yo'qoladi Faqat oxirgi chora sifatida, izoh bilan birga oxirgi chora
Yuqoridan pastga: har bir qadamda kafolat kamayadi

Modul kengaytirish #

8-bobdagi e'lon birlashuvi bu yerda ish beradi - declare module ni bir necha marta yozish mumkin:

TS
declare module "sodda-dokon" {
  export function narxla(nomi: string): number;
}

declare module "sodda-dokon" {
  export function chegirma(narx: number, foiz: number): number;
}
TS
import { narxla, chegirma } from "sodda-dokon";

const a: number = narxla("Olma");
const b: number = chegirma(a, 20);
console.log(a, b);
Terminal
tsc --noEmit && echo "tsc: ikkala elon ham korindi"
Natija
tsc: ikkala elon ham korindi

Amalda bu mavjud kutubxonaga qo'shimcha qilish uchun ishlatiladi - masalan Express ning Request obyektiga foydalanuvchi maydonini qo'shish.

Global kengaytirish #

Eng ko'p uchraydigan holat - muhit o'zgaruvchilari:

TS
console.log(process.env.DOKON_NOMI.length);
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/env.ts(1,13): error TS18048: 'process.env.DOKON_NOMI' is possibly
'undefined'.

Standart holatda process.env ning har bir maydoni string | undefined - to'g'ri, chunki o'zgaruvchi berilmagan bo'lishi mumkin.

Ma'lum o'zgaruvchilarni e'lon qilsak:

TS
declare global {
  namespace NodeJS {
    interface ProcessEnv {
      DOKON_NOMI: string;
    }
  }
}

export {};
TS
process.env.DOKON_NOMI = "Husanboy dokoni";
console.log(process.env.DOKON_NOMI.length);
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/env.ts
Natija
tsc: xato yo_q
15

globalThis ga ham qo'shish mumkin:

TS
declare global {
  var dokonNomi: string;
}

globalThis.dokonNomi = "Dokon";
console.log(globalThis.dokonNomi, dokonNomi);

export {};
Terminal
tsx src/glob.ts
Natija
Dokon Dokon
Global kengaytirish - va'daning yana bir turi

ProcessEnv ga DOKON_NOMI: string deb yozganingizda siz kompilyatorga "bu o'zgaruvchi doim bor" deb aytasiz.

Agar .env faylida u bo'lmasa, dastur ish vaqtida undefined oladi va yiqiladi - tsc esa hech narsa demaydi.

Xavfsizroq yo'l: e'lonni string | undefined qoldirib, dastur boshida bir marta tekshiring:

Natija
const DOKON_NOMI = process.env.DOKON_NOMI;
if (!DOKON_NOMI) throw new Error("DOKON_NOMI berilmagan");

Endi qolgan kod string bilan ishlaydi va va'da haqiqiy tekshiruvga tayanadi.

Ikki bosqichli tasdiqlash #

Kutubxonaning turlari noto'g'ri bo'lsa, as bilan tuzatmoqchi bo'lasiz. TypeScript esa ruxsat bermaydi:

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

const xom: string = "Olma";

const a = xom as Mahsulot;
Terminal
tsc --noEmit 2>&1 | fold -sw 74
Natija
src/ikki.ts(5,11): error TS2352: Conversion of type 'string' to type
'Mahsulot' may be a mistake because neither type sufficiently overlaps
with the other. If this was intentional, convert the expression to
'unknown' first.

Xabar yo'lni o'zi ko'rsatdi:

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

const xom: string = "Olma";

const a = xom as unknown as Mahsulot;
console.log(a.nomi);
Terminal
tsc --noEmit && echo "tsc: xato yo_q"
tsx src/ikki2.ts
Natija
tsc: xato yo_q
undefined

as unknown as T har qanday turni har qanday turga aylantiradi. Natija - undefined, chunki satrda nomi maydoni yo'q.

as unknown as - eng kuchli va eng xavfli yozuv
YozuvKuchi
as TFaqat yaqin turlar orasida
as unknown as THar qanday turdan har qandayiga
@ts-expect-errorBitta qatordagi xatoni o'chiradi

Kodda as unknown as ni ko'rsangiz, yoniga izoh yozilgan bo'lishi kerak: nega bu kerak va qachon olib tashlanadi.

@ts-ignore o'rniga @ts-expect-error ishlating: xato tuzalgach, u o'zi "endi xato yo'q" deb ogohlantiradi.

Xulosa #

  • Turlar uch manbadan keladi: paketning o'zidan, @types/* dan yoki sizning .d.ts faylingizdan.
  • Paket bilan birga keladigan turlar eng ishonchli - ular kutubxona bilan birga yangilanadi.
  • @types/* ni DefinitelyTyped jamoasi yuritadi va u versiyadan orqada qolishi mumkin.
  • Turlanmagan modul TS7016 beradi; allowJs faylni qo'shadi, lekin tekshiruvni kuchaytirmaydi.
  • .d.ts - faqat e'lonlar fayli; declare "amalga oshirish boshqa joyda" degani.
  • declare module "nomi" mavjud bo'lmagan paket uchun ham yoziladi - tsc uni tekshirmaydi.
  • E'lon ichidagi imzolar esa to'liq kuchda ishlaydi.
  • declare module ni bir necha marta yozib, mavjud kutubxonani kengaytirish mumkin.
  • declare global bilan process.env va globalThis ni turlash mumkin - lekin bu ham tekshirilmaydigan va'da.
  • Muhit o'zgaruvchilarini dastur boshida bir marta tekshirib, keyin oddiy string sifatida uzating.
  • as unknown as T har qanday turni aylantiradi; uni faqat izoh bilan birga ishlating.
  • @ts-ignore emas, @ts-expect-error yozing.
Amaliy topshiriq
  1. node:fs dan funksiya import qilib, natijasini noto'g'ri turga berib ko'ring.
  2. node_modules/@types ichida nima borligini ko'ring.
  3. Turlanmagan .js fayl yaratib, TS7016 ni chaqiring.
  4. --allowJs bilan uni qo'shing va tekshiruv yo'qligini tasdiqlang.
  5. Unga .d.ts yozib, noto'g'ri argumentni tutiladigan qiling.
  6. Mavjud bo'lmagan paket uchun declare module yozing va tsc jim turishini ko'ring.
  7. Uni ishga tushirib, ERR_MODULE_NOT_FOUND ni oling.
  8. declare global bilan process.env ga o'z o'zgaruvchingizni qo'shing.
  9. Xavfsizroq variantni - dastur boshida tekshirishni - yozing.
  10. as unknown as bilan satrni obyektga aylantiring va natijasi nega undefined ekanini tushuntiring.

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.