Məzmuna keç
Educora
İrəli20 dəq8 / 8

Müasir üsullar və elan faylları

Ciddi rejimin nələri tutduğunu öyrən, `as const` və `satisfies` ilə dəqiq tiplər al, `.d.ts` elan faylları vasitəsilə üçüncü tərəf JavaScript kitabxanalarını tiplə.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • strict rejiminin hansı yoxlamaları açdığını izah etmək
  • as const ilə qiymətlərdən dəqiq literal tiplər almaq
  • satisfies-i tip annotasiyası və as ilə müqayisə etmək
  • @types paketlərindən istifadə etmək və sadə .d.ts faylı yazmaq

Artıq tipləri, funksiyaları, interfeysləri, birləşmələri, sinifləri və generikləri bilirsən. Bu son dərs peşəkarların hər gün istifadə etdiyi dörd alət haqqındadır: səhvlərin çoxunu tutan ciddi rejim, qiymətlərdən dəqiq tip almaq üçün as const, tipi «genişləndirmədən» yoxlayan satisfies və tipi olmayan JavaScript kitabxanalarını TypeScript-ə tanıdan elan faylları.

Ciddi rejim

tsconfig.json-da "strict": true bir parametr deyil, bütöv bir yoxlamalar dəstidir. Onsuz TypeScript çox şeyə göz yumur və JavaScript-in ən tez-tez rast gəlinən səhvləri keçib gedir. Dəstin ən vacib üzvləri bunlardır:

  • strictNullChecks — null və undefined ayrıca tiplərdir; «ola bilsin undefined» olan qiyməti yoxlamadan istifadə etmək olmaz.
  • noImplicitAny — tipi müəyyən edilə bilməyən parametr səssizcə any olmur, xəta verilir.
  • strictPropertyInitialization — sinfin hər sahəsi elanda və ya konstruktorda qiymət almalıdır.
  • useUnknownInCatchVariables — catch (error) blokunda error dəyişəni any yox, unknown tipli olur.
TypeScript
const users = [
  { name: 'Aysel', age: 15 },
  { name: 'Murad', age: 17 },
];

const found = users.find((u) => u.name === 'Leyla');
console.log(found.age);
Text
users.ts:7:13 - error TS18048: 'found' is possibly 'undefined'.

7 console.log(found.age);
              ~~~~~
find heç nə tapmaya bilər. Ciddi rejim olmasa, kod səhvsiz kompilyasiya olunar və icra zamanı TypeError: Cannot read properties of undefined (reading 'age') ilə çökərdi.
TypeScript
const users = [
  { name: 'Aysel', age: 15 },
  { name: 'Murad', age: 17 },
];

const found = users.find((u) => u.name === 'Leyla');
console.log(found?.age ?? 'not found');
Gözlənilən nəticə
not found
Düzgün həll: ?. və ?? ilə «tapılmadı» halını işləmək.

as const

as const qiyməti «donmuş» kimi qəbul etməyi xahiş edir: sətirlər string yox, dəqiq literal tiplər olur, massiv yalnız oxunan kortejə, obyektin xassələri isə readonly xassələrə çevrilir. Bu, rollar, statuslar və parametrlər kimi sabit siyahılar üçün idealdır və keçən dərsdə danışdığımız enum-u rahatca əvəz edir:

TypeScript
const ROLES = ['admin', 'editor', 'viewer'] as const;
type Role = (typeof ROLES)[number];

function canEdit(role: Role): boolean {
  return role !== 'viewer';
}

const Status = { Active: 'active', Blocked: 'blocked' } as const;
type Status = (typeof Status)[keyof typeof Status];

const s: Status = Status.Blocked;
console.log(ROLES.join(', '), canEdit('editor'), s);
Gözlənilən nəticə
admin, editor, viewer true blocked
Role tipi 'admin' | 'editor' | 'viewer', Status tipi isə 'active' | 'blocked'-dır. Siyahı proqramda da mövcuddur — onu çap etmək və dövrə salmaq olar.
TypeScript
const ROLES = ['admin', 'editor', 'viewer'] as const;
ROLES.push('guest');
Text
roles.ts:2:7 - error TS2339: Property 'push' does not exist on type 'readonly ["admin", "editor", "viewer"]'.

2 ROLES.push('guest');
        ~~~~
as const massivi yalnız oxunan kortejə çevirir, ona görə push metodu yoxdur.

satisfies operatoru

Tip annotasiyası (const x: T = ...) qiyməti yoxlayır, amma dəyişənin tipini T-yə genişləndirir və qiymət haqqında dəqiq məlumat itir. satisfies T isə yalnız yoxlayır: qiymət T-yə uyğun olmalıdır, dəyişən isə TypeScript-in çıxardığı dəqiq tipi saxlayır. Rənglər palitrasında bəzi rənglər sətir, bəziləri isə üç ədəddən ibarət kortejdir:

TypeScript
type ColorName = 'red' | 'green' | 'blue';
type Color = string | [number, number, number];

const palette = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [0, 0, 255],
} satisfies Record<ColorName, Color>;

console.log(palette.green.toUpperCase());
console.log(palette.red[0]);
Gözlənilən nəticə
#00FF00
255
TypeScript green-in sətir, red-in isə kortej olduğunu bilir, çünki satisfies dəqiq tipi saxlayır.
TypeScript
type ColorName = 'red' | 'green' | 'blue';
type Color = string | [number, number, number];

const annotated: Record<ColorName, Color> = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [0, 0, 255],
};
annotated.green.toUpperCase();

const checked = {
  red: [255, 0, 0],
  green: '#00ff00',
  bleu: [0, 0, 255],
} satisfies Record<ColorName, Color>;
Text
palette.ts:9:17 - error TS2339: Property 'toUpperCase' does not exist on type 'Color'.
  Property 'toUpperCase' does not exist on type '[number, number, number]'.

9 annotated.green.toUpperCase();
                  ~~~~~~~~~~~

palette.ts:14:3 - error TS2353: Object literal may only specify known properties, and 'bleu' does not exist in type 'Record<ColorName, Color>'.

14   bleu: [0, 0, 255],
     ~~~~
Birinci səhv: annotasiyadan sonra green sadəcə Color-dır. İkinci səhv: satisfies qiyməti yenə də yoxlayır və bleu hərf səhvini tutur.
YazılışYoxlayır?Dəyişənin tipi
const x: T = valuebəliT (genişlənir)
const x = value satisfies Tbəliqiymətin dəqiq tipi
const x = value as Tdemək olar ki, yoxT

Elan faylları və üçüncü tərəf kitabxanaları

Tərif
Elan faylı (.d.ts)

Yalnız tipləri saxlayan, heç bir icra olunan kodu olmayan fayl. O, JavaScript kodunun TypeScript üçün «təlimatıdır»: hansı funksiyalar var, hansı parametrləri qəbul edir və nə qaytarır.

npm paketlərinin tipləri üç yolla gəlir. Bir çox müasir paket öz .d.ts fayllarını özü ilə gətirir və heç nə etmək lazım deyil. Digərləri üçün icma tipləri ayrıca @types/... paketlərində dərc edir. Heç biri yoxdursa, elan faylını özün yazırsan.

Terminal
npm install lodash
npm install --save-dev @types/lodash
Kitabxananın özü dependencies-ə, onun tipləri isə yalnız proqram hazırlanarkən lazım olduğu üçün devDependencies-ə düşür.

Tutaq ki, layihədə tipləri olmayan köhnə old-slug kitabxanası var — o, mətni URL üçün qısa ada çevirir. Onu import edəndə TypeScript xəbərdarlıq edir ki, modulun tipləri tapılmadı:

Text
src/index.ts:1:21 - error TS7016: Could not find a declaration file for module 'old-slug'. '/home/leyla/blog/node_modules/old-slug/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/old-slug` if it exists or add a new declaration (.d.ts) file containing `declare module 'old-slug';`

1 import slugify from 'old-slug';
                      ~~~~~~~~~~

@types/old-slug paketi yoxdursa, types/old-slug.d.ts faylını yaradıb modulu declare module ilə təsvir edirik. declare sözü deyir ki, bu kod başqa yerdə artıq var, biz yalnız onun tipini bildiririk:

TypeScript
declare module 'old-slug' {
  export default function slugify(text: string, separator?: string): string;
}
types/old-slug.d.ts — gövdəsiz funksiya imzası, yalnız tiplər.
TypeScript
import slugify from 'old-slug';

const title = 'Hello from Baku';
console.log(slugify(title));
console.log(slugify(title, '_'));
Gözlənilən nəticə
hello-from-baku
hello_from_baku
src/index.ts indi səhvsiz yoxlanılır, redaktor parametrləri təklif edir, slugify(42) çağırışı isə TS2345 xətası verəcək.

Öz kitabxananı dərc edəndə .d.ts fayllarını əl ilə yazmaq lazım deyil. tsconfig.json-da "declaration": true parametri ilə tsc hər .js faylının yanında onun .d.ts faylını da yaradır:

TypeScript
export interface User {
    name: string;
    age: number;
}
export declare function greet(user: User): string;
greet.ts-dən yaradılmış greet.d.ts: interfeys və funksiyanın imzası qalıb, gövdə isə greet.js-dədir.

Əsas fikirlər

  • strict: true strictNullChecks, noImplicitAny və digər yoxlamaları açır; onu həmişə aktiv saxla.
  • as və ! səhv mesajını gizlədir, amma problemi həll etmir.
  • as const qiyməti dəqiq literal və yalnız oxunan tiplərə çevirir; (typeof LIST)[number] siyahıdan birləşmə tipi çıxarır.
  • satisfies T qiyməti T-yə görə yoxlayır, amma dəyişənin dəqiq tipini saxlayır.
  • .d.ts faylları yalnız tiplərdən ibarətdir; tiplər paketin özündən, @types/... paketlərindən və ya declare module ilə yazdığın fayldan gəlir.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
tsconfig.json-da "strict": true nə edir?