Асаліны TypeScript: ад першай анатазыі да гэнерыкаў і строгага режыму
Структураваны апавядкі гэтасяброўства типаў у TypeScript — ад прымітываў і ўзнікнення типаў да разліковых аб’еднанняў, гэнерыкаў, типаў-засобаў і строгага tsconfig.
Кожны разработчык JavaScript знае гэты шаблон: код працуе локальна, аплывае на сервер, і чэрез два дні прыходзіць адказ пра баг, таму што функцыя прабрала об’ект заместа строкі, або ў вычысленні патрапіла значэнне undefined. JavaScript не заважае вам пісаць такі код; ён проста выконваецца некоректна, зазвычай у режыме роботы, таму што код запускаецца ў продакшэне. TypeScript пераносіць гэтую проблему на момент, калі вы пісаеце адпаведныя рэквізіты коду. Шырокі практычны карцэг прыводзіць вас ад першага запісу let x: number через механізмы звужэння типаў, дискримінаваных аб’юній, гэнерыкаў і типаў-выконавіцоў да налашоўкаў кампайляра, якія вядомаюць, насколькі захоплення вы насправды атрымуеце, тады як вы зможаце з адной упэўненасцю чытаць і пісаць код на TypeScript для продакшэна.
Што такое TypeScript і чаго ён не ўсё
TypeScript — это мова з адзвярнутым кодам ад Microsoft, якая дадае JavaScript статычную систему типаў. Пад «статычным» тут маесяцца на увазе, што кампайляр перакантрацуе типы ўсё раней чым запускае програму, у вашам рэдагары или пад час кампайлявання, а не пасля ўжывання. Тры факты вялікай меры адпраўляюць усё іншае:
- Цяперашняя мова ёсць супернабор JavaScript. Будзь-які сынтаксычна правільны код на JavaScript таксама є правільным сынтаксычна на TypeScript, таму вы проста расширяеце тое, што вядома ўжо, а не пачынаеце з нуля. Кампайляр усё ж можа паведаміць пра аблыканні ў таком кодзе, і гэта самэ прычына.
- Ён кампайляецца у звычны JavaScript. Браузеры і Node.js запускаюць JavaScript, таму кампайляр
tscадключае всі анотацыі і стварае звычныя файлы.js.
Разлік у адной функцыі
Ёсць звычная функцыя JavaScript, якая дадзеўнае два значэння:
function add(a, b) {
return a + b;
}
Калі яе вызваць з рэчым і цяжарам, яна не выклікае памылак. Яна з’едначае іх, і вы заўважыце гэта толькі тады, калі сума на рахунку-фактуре будзе незвычайная:
add("10", 20); // "1020" — silently wrong
Указванне тыпа параметра і рэзультата чыста адзначае умовы викорыстання функцыі:
function add(a: number, b: number): number {
return a + b;
}
Тепер той самы вызов будзе адхілён, калі вы яшчэ рэдагуеце код, пры чым памылка будзе паказана адразу пад некоректным аргументам:
add("10", 20);
// Error: Argument of type 'string' is not assignable to parameter of type 'number'.
Стварэнне проекта
Пасля установкі Node.js вы можете установіць кампайлер глобальна і пераканацца, што ён працюе:
npm install -g typescript
tsc --version
Для рэальных проектаў установіце TypeScript як локальную залежнасць для разработкі, каб усі учаснікі тыму і сервер CI выкарыстоўвалі аднаковую версію, пасля чаго створыце файл налаштавання:
npm install typescript --save-dev
npx tsc --init
Створанный файл tsconfig.json яўляецца панеллю керування, якая выбірае, насколькі строгім і савременным должна быць кампайляр. Няўзабавныя версіі tsc --init вже актываюць режым strict, а TypeScript 6.0 зробіў строгі режым стандартным, але старэйшыя проекты часта працуюць з менш строгімі налаштаваннямі, якія пазней допраўляюцца. У роздзеле налаштавання нижэй гаворыцца пра гэтым.
Мінімальны першы файл адзначае зменную з типам і выводзіць яе:
// app.ts
let message: string = "Hello, TypeScript";
console.log(message);
Скомпілюйце яго, а пасля запустыце створаны JavaScript:
tsc app.ts # produces app.js
node app.js # Hello, TypeScript
У практыцы большэйшыя проекты ухілляюцца ад такога двухэтапнага падходу і запускаюць файлы за допаможчынай ts-node або tsx, альбо выкарыстоўваюць інструменты для збірання коду, такія як Vite, esbuild чытае webpack, які компілюе код у рэальны час. Іноды цяпер жа зробіць гэта вручную мае сенс, адколі гэта дапамага закрепіць правильную канцэпцыю: увайшае TypeScript, а выходзіць JavaScript.
Базовыя типы і ўзнакомленне
Прімітывы і масівы
Анотацыі прімітываў — це string, number і boolean:
let username: string = "sanajit";
let age: number = 26;
let isActive: boolean = true;
Масівы пішучыся з типам элемента, які следуе за квадратнымі скобкамі:
let scores: number[] = [90, 85, 78];
let tags: string[] = ["typescript", "javascript"];
Генерычны формат Array<number> означае абсолюйна тое ж самае; выберыце адны стыль і настойчыва яго выкарыстоўвайце:
// equivalent generic syntax
let ids: Array<number> = [1, 2, 3];
Дазвольце ўзнакомленню выканаць звычную роботу
Рэдкасць, калі трэба адзначаць заснаваныя зменны. TypeScript выважвае тып на адказе і пасля чаго прыменяе яго:
let city = "Ahmedabad"; // inferred as string
city = 42; // Error: Type 'number' is not assignable to type 'string'
Запіс let city: string = „Ahmedabad“ не ўскладнена, проста зайвая. Хорашыя правілы для всіго языка: паважаць выважванне, калі адказ робіць тып явным, і пісаць явныя тыпы там, дзе адказ є неодназначным або калі вы визначаеце контракт, такі як параметры функцый, тыпы адказаў, порожнія масівы і сігнатуры калебакаў.
any, unknown, never і void
Этыя чатыры спецыяльныя тыпы ствараюць проблемы практычна кожнаму пачатківцу:
anyвыключае перакананне тыпу для адказа. Це спосаб выйсця з проблемы, а не справжні тып, і частае ўжыванне яго — гэта найпашырэнейшы спосаб, калі кодавая база ператвараецца на JavaScript з дадзенай синтаксысам.
unknown — гэта безпечны аналаг. Яму можа быть прызначана будзь-яка значэнне, але яго нельга выкорыстоўваць, пакуль яго не будзе адганяча перапыткай. Гэта правы выбар для дадзенняў, форма якіх ўсё ще не вядома, напрыклад, для адпаведзення API перад паўнай верыфікацыёй.never — гэта значэнне, якое не можа існаваць, напрыклад, рэзультат функцыі, якая завжды выклекае або ніколи не вяртае значэнне. Яго самая практычная наявнасць — у перапытках выключнай ўсе можлівасці, калі компілятор павінен пераканацца, што кожны варыянт switch адобразжаны.void — гэта пазначэнне для функцыі, якая не вяртае нічога корыстнага, напрыклад, для обробні адбуванняяў чы пакрыцца для логавання.За дапамогою unknown перапытка typeof адкрывае метадзеі для строк толькі ў захаванай галузі:
function process(value: unknown) {
if (typeof value === "string") {
console.log(value.toUpperCase()); // safe — narrowed to string
}
}
Функцыя, яка завжоды выклікае аберанцію, мае тип never, тады як функцыя, яка проста выконвае побачны эфект, вяртае void:
function fail(message: string): never {
throw new Error(message);
}function logAction(action: string): void {
console.log(`Action: ${action}`);
}
Па конкрэтныя способы замены any у распашчытых ситуаціях, адзірніце шасць спосабоў безпечнай замены any.
Апісаванне об’ектаў за дапамойкай інтэрфейсаў та псевдонімаў типаў
Форму об’екта можна запісаць унутрошняя:
const employee: { id: number; name: string; active: boolean } = {
id: 1,
name: "Amit",
active: true,
};
Это працюе аднойчы, але павтарэнне той самай унутрошняй формы ў всіх месцах быстра становіцца непатрэбным шумам. Назваўшы форму interface або type, можна гэта рашыць.
Інтэрфейсы
Інтэрфейс называе форму об’екта, ўжо каб можна было яго перысваяць:
interface Employee {
id: number;
name: string;
department: string;
}
Кожны об’ект, анотаваны ім, должен падходзіць да заявленых полей:
const employee1: Employee = { id: 1, name: "John", department: "IT" };
const employee2: Employee = { id: 2, name: "Sara", department: "HR" };
Знак запытання пазначаець атрыбут, які можа не існаваць:
interface User {
id: number;
name: string;
phone?: string; // may or may not be present
}
Атрыбуты readonly можна прызначаць пад час стварэння об’екта, але не пасля таго:
interface Product {
readonly id: number;
name: string;
}
Прабаўка перапрызначыць такі атрыбут вызывае памылку часу кампайлявання:
const laptop: Product = { id: 100, name: "MacBook" };
laptop.id = 200; // Error: Cannot assign to 'id' because it is a read-only property
Інтэрфейсы таксама можу распрастарвацца адна ў аднаго, што дазволяе дзеліцца спяльнымі полямі без ўсунення іх. Пачніце з базовага шэйпу:
interface Person {
name: string;
age: number;
}
Потым створыце болей спецыфічны шэйп на його аднойчыне:
interface Employee extends Person {
employeeId: number;
department: string;
}
Аліясы типаў
Аліяс type таксама можа даваць назву формам об’ектаў, але не ўскладнены толькі імі. Юніі, прымітывы і туплы таксама можна назваць такім спосабам:
type ID = string | number;
type Point = { x: number; y: number };
type Status = "pending" | "shipped" | "delivered";
Выбор межа інтэрфейсам і типам
Для звычных форм об’ектаў гэтыя два элементы ў большай частцы можна заменіць адным на другі. Рэальныя разлікі заключаюцца ў:
- Расшырэнне: інтарфейсы выкарыстоўваюць
extends; алясы типа спаўнююць формы за дапамою аператара перасекання&. - Аднасці і прымітывы: іх можна выразіць толькі за дапамою алясаў типа, як у
type A = string | number. - Злучэнне декларацый: два інтарфейсы з адной назвай злучаюцца ў адны; алясы типа не можна перадеклараваць.
- Стандарт: інтарфейсы звычайна викорыстоўваюцца для форм публічных API і контрактаў класаў; алясы типа — для аднасцей, туплікаў і карэльваваных або умовных типаў.
Правіло, якое прыменяе большасць команд: выбірайце interface, калі форма, верагатна, будзе расшыроўвана, напрыклад, для прапсаў React, модэляў API і контрактаў класаў, а type — для аднасцей, туплікаў і всіх не-об’ектных типаў.
Аднасці, звужэнне і перасекання
Тыпы аднасці
Союз можа мець значэнне, якое ўзімае аднойчы ад кальколькох типаў:
function printId(id: string | number) {
console.log(`Your ID is ${id}`);
}
Оба выклікі нижэй прыманяюцца, таму што кожны аргумент падходзіць да аднаго з членаў союзу:
printId(101);
printId("A-204");
Спяканне
Калі значэнне прызначаецца як союз, TypeScript дазволяе толькі тыя аперацыі, якія ўзімаюцься паўнай меры для кожнага члена, пакуль не будзе падтверджана які самэ член выкарыстоўваецца. Гэта падтверджэнне называецца спяканнем, і кампайлер следуе за яным у всіх ветках програмы:
function formatValue(value: string | number) {
if (typeof value === "string") {
return value.toUpperCase(); // TypeScript knows it's a string here
}
return value.toFixed(2); // and here, it knows it's a number
}
Па-разоў з typeof, распашчытныя засобы спякання – это Array.isArray(), instanceof, апэратар in і пераказы роўнасці з null або undefined. Самэ так TypeScript за звычайных адзначэнняў застаецца мовчазным, але ўсё ж выяўляе нестандартныя ситуацыі.
Дискримінаваныя союзы для стану
Самыя частая памятка, якую не спрыгваюць розробнікі среднага рангу, — это стварэнне спяльнага літэральнага поля „tag“ для кожнай варыянтной формы аб’юнкціі. Спачатку неабходна отдзельная дэфініцыя кожнага стану:
type LoadingState = { status: "loading" };
type SuccessState = { status: "success"; data: string[] };
type ErrorState = { status: "error"; message: string };
Потым іх неабходна саюзаваць і выбіраць стан па значэнні tag:
type FetchState = LoadingState | SuccessState | ErrorState;function render(state: FetchState) {
switch (state.status) {
case "loading":
return "Loading...";
case "success":
return `Loaded ${state.data.length} items`;
case "error":
return `Failed: ${state.message}`;
}
}
У кожнам case значэнне state сузваецца да падходячага варіанта, таму state.data ўзможна выкарыстоўваць толькі у галузі "success", а state.message — толькі у галузі "error". Немагчымыя комбінацыі, такія як наявнасць дадзеных і памылкі адночасна, проста не можуць быць представлены. эта мера пазбегае цэлай категоріі збоев типу "аспект не вызначаны" у коде UI і API. Дадаць галузь default, якая прызначае state зменнай never, ператварае гэта на перакананне аб усепакрытасі: якщо пазней дадаць чэрговы статус, кампайлер пакажае кожны элемент switch, які яго не урахаваў.
Тыпы перасекання
Дзе альянс означае "гэта або тое", перасеканне означае "гэта і тое". Пачніце з двух маленькіх форм:
type Timestamped = { createdAt: Date };
type Named = { name: string };
Для стварэння перасекання об’екту неабяжнае, каб у яму былі поля з обох:
type Record = Timestamped & Named;const item: Record = { name: "Invoice", createdAt: new Date() };
Адзін застерэжны момент па гэтым прыкладу: Record таксама ўжо ёсць назва вбудованага типу-інструмента. Адзначэнне савастой псевдоніма з гэтай назвай засланяе глобальны тип у тым файле, што ў найкращым случае вызывае плутанне, таму ў рэальным кодзе краща выбіраць болей спецыфічную назву.
Функцыі
Анотацыі параметраў і рэзультатаў ёсць адной з основных частак кантракту функцыі:
function multiply(a: number, b: number): number {
return a * b;
}
Неабяжныя параметры пазначаюцца знакам ?; значэння за значчынай робяць параметр неабяжным і визначаюць яго тип, а параметры-рэст збіраюць будзь-сколькі аргументаў у масэвы типаваны массив:
// optional parameter
function greet(name: string, title?: string): string {
return title ? `${title} ${name}` : name;
}// default parameter
function createOrder(item: string, quantity: number = 1) {
return { item, quantity };
}// rest parameters
function sum(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0);
}
Тыпы функцый
Можна таксама апісаць форму самай функцыі, што ўжо корыстна для калебакаў і об’ектаў-стратэгій:
type MathOperation = (a: number, b: number) => number;
Функцыя, прызначаная для такага типу, абяраецца тыпамі своіх параметраў з анатазацыі, таму a і b не патрабуюць сабстаячых анатазацый:
const subtract: MathOperation = (a, b) => a - b;
Класы і модифікаторы доступу
Класы TypeScript — это класы JavaScript з типаванымі атрыбутамі і модифікаторамі доступу. Клас нижэйша спачатку абяраецца прыватным значэнням балансу і атрыбутам owner, які можа быць чытаны толькі:
class Account {
private balance: number;
readonly owner: string;
У рэште класа гэтыя атрыбуты задаюцца ў канстрактары, а таксама выклікаюцца методы для змены і чытання балансу; доступ да прыватнага атрыбута зза меж класа заблокаваны:
constructor(owner: string, initialBalance: number) {
this.owner = owner;
this.balance = initialBalance;
} deposit(amount: number): void {
this.balance += amount;
} getBalance(): number {
return this.balance;
}
}const acc = new Account("Priya", 1000);
acc.deposit(500);
console.log(acc.getBalance()); // 1500
acc.balance; // Error: Property 'balance' is private
Модифікаторы значаць:
public, які ўзяты за звычку, доступны паўсюду.privateдоступны толькі ўнутрь класа.protectedдоступны ўнутрь класа і яго падкласаў.
readonly лямды прымаюць значэнне ў канстрактары і не дазволяюць пазнейшае перазначэнне.Памятайце, што private рэалізуецца толькі за дапамою кампайляра; пад час выканання атрыбут ёсць звычайной лямдой. Якщо вам патрэбна справжня прыватная адзインформацыя пад час выканання, для этага існуюць # лямды ў JavaScript, пра якія йдзе мова ў TypeScript private fields versus # syntax.
Інтэрфейсы як кантракты класаў
Інтэрфейс можа визначыць, што клас павінен запростаць:
interface Shape {
area(): number;
}
За дапамою implements кампайляр пераканальваецца, што клас выпалняе кантракт, і пра відсутнюй метод паведамляецца да таго, як код запускаецца. Канстрактар таксама выкорыстоўвае атрыбут-параметр private radius, які адгласоўвае і прызначае лямду ў аднам кроку:
class Circle implements Shape {
constructor(private radius: number) {} area(): number {
return Math.PI * this.radius ** 2;
}
}
Гэнерыкі: код, які можна викорыстоўваць знову і які захоўвае сваія типы
Гэнерыкі — гэта тады, калі TypeScript перестае адчувацца як проста анотаваны JavaScript і стае сэрцам іншага інструмента.
Проблема, якую яны рашаюць
Памочную функцыю, якая вяртае першы элемент будзь-каго масіву, можна напісаць з викорыстаннем any:
function firstElement(arr: any[]) {
return arr[0];
}
Яна працюе, але інфармацыя пра тип згубляецца пад час вывароту, і кожны рэзультат є any:
const num = firstElement([1, 2, 3]); // typed as `any` — no help from the compiler
const str = firstElement(["a", "b"]); // also `any`
Параметр типу зафіксавае тип элемента вхідных дадзеных і перыяктвае яго для значэння, яке вяртаецца:
function firstElement<T>(arr: T[]): T {
return arr[0];
}
Тепер кожны вызов дае точны тип рэзультата, які выважваецца на адной з аргументаў:
const num = firstElement([1, 2, 3]); // inferred as number
const str = firstElement(["a", "b"]); // inferred as string
T — гэта зменная типу, якую TypeScript запоўняе на адповіднасць таму, што вы прасілі. Вы застаецеся з гнучкасцю any, але атрымуеце безпеку конкрэтнага типу. Заўважыце, што з порожнім масавым элементам arr[0] на час выконання фактычна ёсць undefined; увімкненне noUncheckedIndexedAccess змушвае кампайлер практычна выразіць гэта як T | undefined.
Генерычныя інтерфейсы
Генерыкі таксама працуюць з інтерфейсамі. Адны обгорак для адпаведзення можа описваць кожную точку выходу:
interface ApiResponse<T> {
success: boolean;
data: T;
}
Тып паданых дадзенняў задаецца там, дзе викорыстоўваецца обгорак:
const userResponse: ApiResponse<{ id: number; name: string }> = {
success: true,
data: { id: 1, name: "Sara" },
};
Самэ так багато прыкладных програм пішуць свой шар API: адна зменная ApiResponse<T>, якая пераўтвараецца для корыстувачаў, продуктаў, замовленняў і ўсьго іншага, што вяртае бэкенд.
Обмежэнне параметра типу
Інодзе T павінен гарантаваць певныя якосці. Апісацыю выкалекі трэба практыкаваць у вачынку-інтерфейсе:
interface HasLength {
length: number;
}
Пасля чаго параметр трэба обмежыць за дапамою extends, ўнаследаваючы толькі тыпы, якія маюць атрыбут length:
function logLength<T extends HasLength>(item: T): void {
console.log(item.length);
}logLength("hello"); // OK — strings have .length
logLength([1, 2, 3]); // OK — arrays have .length
logLength(42); // Error: number doesn't have .length
Тыпы-дапаможнікі
TypeScript прывозыць гэнерычныя тыпы-дапаможнікі, якія ствараюць новыя тыпы на адной з існуючых, заменяючы вельмі большую частку ручна напісанага шаблонавага коду. Дадзім модель корыстніка:
interface User {
id: number;
name: string;
email: string;
isAdmin: boolean;
}
Можна ствараць варіанты заместо таго, каб перазаявляць іх: Partial робіць кожную якосць неабяжнаю, Readonly — усі якосці толькі для чытання, Pick заставае выбраныя ключы, Omit ўсуне іх, а Record стварае тып-слоўнік:
// Every property becomes optional — perfect for "update" functions
type UserUpdate = Partial<User>;// Every property becomes read-only
type ImmutableUser = Readonly<User>;// Pick only the fields you need
type UserPreview = Pick<User, "id" | "name">;// Everything except the fields you list
type PublicUser = Omit<User, "email" | "isAdmin">;// A dictionary shape: keys of one type, values of another
type UsersById = Record<number, User>;
Тыповым прыкладам ўжыцця являецца функцыя апдэйта, якая прыме нальотнае падмножыну полей:
function updateUser(id: number, changes: Partial<User>): void {
// merge `changes` into the stored user
}
Апыляючыя функцыю пасылаюць толькі тое, што зменілася:
updateUser(1, { name: "New Name" }); // no need to pass email, isAdmin, etc.
Адаптаванне блога па тэму вбудованых функцыянальных типаў TypeScript дэталізавае ўсю ўпорку такіх типаў.
Enum-ы і літэральныя типы
Enum-ы
Enum задае іменаваны набор сталярых значэнняў:
enum OrderStatus {
Pending,
Shipped,
Delivered,
}
Значэнні пасля чаго апыляюцца чераз enum:
let status: OrderStatus = OrderStatus.Shipped;
Па значэнню члены нумеруюцца ад 0. Асабліве калі прызначаюцца строкавыя значэнні, логі і даны, якія пераходзяць праз сеть, становяцца значна простыяя для дыбагавання:
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
Аднасоюзы строкавых літэраляў часта ёсць простыяя
Многія команды сэрцава выбіраюць аднасоюз строкавых літэраляў, таму што ён не стварае дапынковага JavaScript-кода і працуе прыведамлівей:
type OrderStatus = "pending" | "shipped" | "delivered";
Кампайляр такім чынам адхоўвае будзь-якія значэнні, якія не належаць да заданага набору:
function updateStatus(status: OrderStatus) {
// ...
}updateStatus("shipped"); // OK
updateStatus("cancelled"); // Error: not assignable to type 'OrderStatus'
Існуе ўтолькі іншы практычны адказ на выбор уніянаў: энумы генеруюць код пад час выканання, таму інструменты, якія адключаюць толькі типы, такія як вбудованая падтрымка TypeScript у Node.js, не прыймаюць іх.
Модулі і tsconfig.json
Модулі
TypeScript выкарыстоўвае стандартную сынтаксі ES-модуляў. Адна файл выэкспортуе функцыю:
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
Іншы файл яе імпортуе:
// app.ts
import { add } from "./math";
Найважлівейшыя настройкі
У генераванай конфігурацыі є дзесяткі опцый, але толькі калька з іх вплывае на большую частку вашага досвіду работы:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "./dist"
}
}
strict: trueактывае весь комплекс строгіх пераканальненняў, укладаючыstrictNullChecks, які вымагае частковага адносу даnullіundefined. Апытныя разработчыкі вважаюць гэта непрыемлемым, таму што без гэтага TypeScript выявляе значна менш справжніх багоў.
noImplicitAny адваруе пра абэранцыі там, дзе значэнне іншым чынам перайшла бы на any без вашага запиту. Ён уже ўключаны ў режым strict, таму яго отдзельныя паказанні маюць значэнне толькі для лёгкасупрацоўнасці.target адначасова вяршыць выбіранне версіі JavaScript, якая будзе выканана, і вяршыць тое, насколькі савэтнай синтаксі трэба перапісваць для старэйшых средаваў.Калі вы спадчынаеце кодавую базу з выключаным режымом strict, правільны падход — ўвёсці яго і поступова усунуць абэранцыі, працюя з кожным файлам окрема, а не проста додаць any, пакуль не знікнуць адзначэнні пра абэранцыі.
Пашчутныя працынкі на кожным рэвэле
Пачатківцы
- Адзначэнне значэнняў, якія TypeScript і так мог бы вывучыць сам.
- Вжыванне
anyяк толькі компайлер падае адзначэнні пра абэранцыю, замест таго каб звузіць рэальны тип.
Середній ранг
- Акларацыя
interfaceабоtypeдля екземпляра, які могаў бы адразу обработаць інферэнс, што прыносіць толькі зайвую формальнасць без рэальной парады. - Указванне масоў як зменных і ўтварэнне змян у іх за дапамогою
pushабоsplice, калі ўсё ж трэба было викорыстоўвацьReadonlyArray<T>і здзейснюваць змяны толькі без змены структуры. - Забыванне пра тое, што аб’еднанне (union) павінна быць спачатку сузана, прычымо да таго — спробы борцавання з кампайлярам уместо чытання його паведамленняў.
Прасунуты ранг
- Стварэнне генерыкаў без жадных абмежэнняў, якія могу быць чым завалям, што таямніча паслабляе сэнс викорыстоўвання генерыкаў у функціях.
- Выключэнне режыму
strictдля всіго проекта, каб спрыяць адхоўленню кальколькі памылак, уместо таго, каб іх выправіць аб адгуклаць у певныя рамкі. - Спрытліванне такога тыповага асэрцыі, як
value as Type, так, нібыта ёна паўнастае якія-небудзь данні. Асэрцыя нічога не пераканальвае пад час выконання; яна проста кажа компілятору даваць вам доверле. Данні з зяўніх адносна вашага програмы, укладаючы ў сябе адпаведзі AI, данні, якія вводзі корыстувальнікі, іlocalStorage, патрабуюць рэальнай пераканальвання.
Галоўныя выводы
- TypeScript дадае кампіляцыйны пераканальвач да JavaScript; тыпы зникаюць, калі код запускаецца, таму межы пад час выконання все рава патрабуюць пераканальвання.
- Анотавайце контракты, такія як падписы функцый і порожнія колекцыі, і дазвольце механізму аўтадыдакшні займацца рэштаю.
- Ўжывайце
interfaceдля об’ектаў, якія можна расшырваць, іtypeдля з’еднанняў, туплі і необ’ектных тыпаў. - Як можно раней выучыце концэпцію дискримінаваных з’еднанняў; гэта самы спосаб, які найбольш безпасна запобегае багам у кодзе з великай колькасцю станоў.
- Універсальныя тыпы і функцыйнальныя типы, такія як
Partial,Pick,OmitіRecord, якраз і ператвараюць розрозненыя анотацыі на справжняю систему тыпоў. - Заставайце параметр
strict: trueувімкнутым. Галоўная перавага TypeScript — гледзець на помылкі яшчэ на пачатку, калі ўсё легка выправіць, а не пазней, калі це будзе коштаць дорожа, і гэта можліва толькі тады, калі перакрытчык можа вядома выплявляць свою роботу.
Спадні матэрыялы
- Шасць тэхнік TypeScript, якія ператвараюць тыпы на рэальную прымусовую практыку запобежнення багоў — Дазнаецеся, як параметры satisfies, анунцыі з тагамі, прыем “never checks”, тип “unknown”, похадныя тыпы і ідэнтыфікаторы з маркірамі дапамагаюць TypeScript выловляць справжнія багі ў часе компілявання, а не пад час роботы програмы.
- Модэлюванне домэнаў у TypeScript: за межамі базавых анатакцый типаў — Выучыце практычныя прыемы работы з TypeScript – ад разліку межу “unknown” і “any” да дзелячыхся аюніяў і выкарыстоўвання ключавых слов “satisfies” – якія дапамагаюць модэлюваць правядзімыя станы, а не проста пазначаць данні.
- Асновы цыклаў у TypeScript: while, do-while, for, break і continue — Выучыце, як цыклы while, do-while і for у TypeScript ацэнююць сваія умовы, чаму змена дыапазона значэнняя цыкловай зменной паўтарае рэзультаты, і як ключавыя слова break і continue зменяюць тэкстуру виконання коду.
- Пяшанне працэйнасоўнай роўнасці ў JavaScript: ===, ==, працэйнаныя аператары і Object.is — Дазнаецеся, як строгая і нестрогая роўнасць, працэйнаныя порэванання і Object.is насправдзе вядуць да выявлення аднаковасці ў JavaScript, а таксама пра пасткі прымусовага пераканвання, якія крыюцься за кожным з іх.