12 серпня Microsoft представила TypeScript 4.4 Release Candidate (RC). Це означає, що всі зміни готові й офіційний стабільний випуск опублікують незабаром, після кількох додаткових виправлень помилок.
Тож подивимось, що у TypeScript нового, як це може вплинути на вашу розробку та як спробувати новинки вже зараз!
Значні зміни
Поглянемо спочатку на критичні оновлення. У цьому випуску є кілька таких змін: не надто великих, але цілком здатних зламати ваш код:
-
Відтепер не можна ініціалізувати абстрактні властивості всередині абстрактних класів. Можна лише визначити їхній тип.
-
Поліпшилась перевірка
Promise
. Тепер TS частіше нагадуватиме вам додати функціюawait
, коли ви перевіряєте результатиPromise
черезif
; так можна буде уникнути непотрібних перевірок. -
Типово параметрами
catch
тепер будутьunknown
замістьany
, коли ввімкнено\\--strict
або новий прапор\\--useUnknownInCatchVariables
. -
Значення
this
не враховується під час виклику імпортованих функцій для узгодження зі специфікацією модулів ECMAScript у всіх доступних системах модулів (ESM, AMD, CommonJS тощо). -
lib.d.ts
змінено, щоб воно відповідало поточним специфікаціям (особливоlib.dom.d.ts
з усіма зазначеними тут змінами).
Тепер розгляньмо, які ще суттєві функції з'являться у TypeScript.
Поліпшення інструменту виявлення типів Type Guard
Чи не найважливішою особливістю TypeScript 4.4 є «аналіз потоку керування умовами аліасингу (aliased conditions) та дискримінантами».
Це означає, що відтепер аліасинговані/накладені type guards, навіть з дискримінаційним об'єднанням, будуть належно проаналізовані та використані для звуження потрібного типу.
У попередніх версіях TS такий код не спрацював би.
const example = (arg: string | number) => {
const isString = typeof arg === "string";
if (isString) {
return arg.toUpperCase(); // Помилка
}
return arg.toPrecision(); // Помилка
};
Умова isString
не могла повідомити TS, що arg
буде string
, коли твердження правдиве. У результаті TS видає помилку, коли ви застосовуєте специфічні для типу методи та властивості, думаючи, що тип arg
це string | number
. Лише розміщення умови у твердженні if
було правильно інтерпретоване.
З удосконаленим аналізом керування потоком у TS 4.4 це більше не буде проблемою. До того ж TS виявлятиме належні типи під час роботи з дискримінованими об'єднаннями, навіть під час перевірки деструктуризованих властивостей!
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; sideLength: number };
const area = (shape: Shape): number => {
const { kind } = shape;
const isCircle = kind === "circle"; // shape.kind === "circle" теж працюватиме
if (isCircle) {
// Circle
return Math.PI * shape.radius ** 2;
}
// Square
return shape.sideLength ** 2;
};
До певної глибини TS також розпізнає складніші комбіновані умови та відповідно звужує тип.
const example = (x: string | number | boolean) => {
const isString = typeof x === "string";
const isNumber = typeof x === "number";
const isStringOrNumber = isString || isNumber;
if (isStringOrNumber) {
x; // string | number
} else {
x; // boolean.
}
};
Що ж, ці вдосконалення дійсно чудові! Розробники, які працюють з TS, тепер зможуть гарно компонувати та анотувати складні умови, не вписуючи все у свої твердження if
чи твердження прямого типу.
Гнучкіші підписи індексів
Ще одне значне вдосконалення — це підписи індексів. Ви більше не будете обмежені типами number
та string
— тепер з'являться й symbol
та шаблони рядків.
interface Colors {
[sym: symbol]: number;
}
const red = Symbol("red");
const green = Symbol("green");
const blue = Symbol("blue");
const colors: Colors = {};
colors[red] = 255;
colors[red]; // number
colors[blue] = "da ba dee"; // Помилка
colors["blue"]; // Помилка
Підписи індексів symbol
— це непогано. Однак підписи індексів шаблонів рядків значно цікавіші! Вони дозволять звузити підпис індексу до певного шаблону, тож створювати складні визначення типу стане простіше, ніж будь-коли.
interface Example {
a: number;
b: string;
[prop: `data-${string}`]: string;
}
const test1: Example = {
a: 1,
b: "example",
"data-test": "example",
};
const test2: Example = {
"data-test": "example",
}; // Помилка (ні "a" ні "b")
const test3: Example = {
a: 1,
b: "example",
test: "example",
}; // Помилка ("test" не прийнято)
Якщо ви коли-небудь хотіли застосовувати підпис індексу, але відособити його від string
, це оновлення стане для вас дуже корисним.
До того ж будуть дозволені об'єднані підписи індексів. Допустимі будь-які поєднання string
, number
, symbol
та шаблону рядка.
interface Example {
[prop: string | number]: string;
}
Точні опційні типи властивостей
Окрім \\--useUnknownInCatchVariables
, з'явився ще один прапор — \\--exactOptionalPropertyTypes
.
Якщо він увімкнений, TS більше не дозволятиме ініціалізацію опційних властивостей з undefined
.
interface Example {
a: string;
b?: number;
}
const test: Example = {
a: "example",
b: undefined, // Помилка, якщо увімкнено --exactOptionalPropertyTypes
};
Така поведінка визначає, чи справді властивість наявна в об'єкті (зі значенням undefined
чи якось інакше), і це корисно у кількох випадках.
Наприклад, коли використовується Object.assign
або об'єктне розширення ({ …obj }
), властивості з undefined
насправді обробляються інакше, ніж дійсно відсутні властивості. Залежно від реалізації, те саме може бути справедливим і для вашого коду.
Щоб дозволити undefined
з увімкненим \\--exactOptionalPropertyTypes
, вам доведеться явно включити undefined
до типу об'єднання. Без прапора така поведінка буде автоматичною.
interface Example {
a: string;
b?: number | undefined;
}
const test: Example = {
a: "example",
b: undefined, // Працює правильно (навіть якщо увімкнено --exactOptionalPropertyTypes)
};
Оскільки цей прапор може спричинити проблеми як у вашому коді, так і у сторонніх визначеннях (наприклад, з DefinitelyTyped), він не входить до \\--strict
і тому є опційним та не спричиняє збоїв.
Якщо ви вважаєте, що це може знадобитися у вашій кодовій базі, увімкніть цей прапор разом із \\--strictNullChecks
.
Блоки Static у класах
Останнє велике оновлення — блоки static
.
Це майбутня можливість ECMAScript, яка зараз на третьому етапі пропозиції. Блоки static
дозволяють складніший процес ініціалізації частин класу static
.
class Example {
static count = 0;
// Блок Static
static {
if (someCondition()) {
Example.count++;
}
}
}
Хоча це вже працює, оновлення робить процес простішим і значно елегантнішим, дозволяючи блоку ініціації перебувати прямо у визначенні класу.
Раніше таку логіку доводилося виводити за межі визначення класу, тож вона була окрема та громіздка.
class Example {
static count = 0;
}
if (someCondition()) {
Example.count++;
}
Крім того, блоки static
мають ще одну перевагу: вони відкривають доступ до приватних статичних полів та полів екземплярів (з огляду на те, що вони є частиною визначення класу). Це дає можливість ділитися їхніми значеннями з іншими класами або функціями, доступними в тій же області видимості.
let exampleFunc!: (instance: Example) => number;
class Example {
static #accessCount = 0;
#initial: number;
constructor(input: number) {
this.#initial = input * 2;
}
static {
exampleFunc = (instance: Example) => {
Example.#accessCount++;
return instance.#initial
}
}
}
if (exampleFunc) {
exampleFunc(new Example(2)); // 4
}
Вдосконалення швидкодії
Окрім нових можливостей та значних змін, як завжди, є й кілька помітних вдосконалень швидкодії:
- Швидше оголошення (declaration emits) завдяки додатковому кешуванню.
- Умовна нормалізація шляху економить час компілятора, тож завантаження пришвидшилось.
- Швидше зіставлення
paths
уtsconfig.json
завдяки додатковому кешуванню, це теж покращує продуктивність. - Швидша інкрементна збірка зі
\\--strict
завдяки виправленню помилки, що спричиняла непотрібну перевірку типів під час кожної збірки. - Швидше створення асоціативного масиву джерел для великих виводів.
- Швидша збірка за допомогою
\\--force
, адже тепер є менше зайвих перевірок.
Вдосконалення Intellisense
Найвідоміша частина TS — intellisense (автодоповнення/підтримка редактора) — також суттєво поліпшилась.
Оскільки пропозиції TS стають все кращими, починаючи з 4.4, він автоматично видаватиме пропозиції написання для чистих файлів JavaScript без увімкнених checkJs
або @ts-check
. Це будуть неінвазивні пропозиції на кшталт: «Did you mean…?».
Серед інших помітних поліпшень — вбудовані підказки, відомі як inline hints або ghost text. Вони можуть застосовуватися до всього, від назв параметрів до отриманих типів повернення.

Також вдосконалено пропозиції шляхів імпорту. Замість хибних відносних шляхів, як-от node_modules/..
, TS показуватиме шляхи, які ви справді застосовуєте. Наприклад, react
замість node_modules/react/..
або щось схоже. Косметична, але хороша зміна.

Спробуймо?
Імовірно, вам вже кортить скористатись усіма цими чудовими можливостями. Найкраще було б дочекатися стабільного випуску ще кілька тижнів. Тоді вам не доведеться мати справу з нерозв'язаними помилками та іншими проблемами.
Однак, якщо ви хочете спробувати версію RC зараз, то можете отримати її за допомогою NPM:
npm install typescript@rc
Потім, за потреби, виберіть її для користування у своєму IDE чи редакторі коду.
Природно, що у VS Code ви отримаєте найкращу якість роботи, а у VS Code Insiders ви отримаєте найновішу версію TS у комплекті.
Підсумуймо
Ну, нарешті! У TS 4.4 з'явиться безліч нововведень, а заплановано їх ще більше. Якщо ви користуєтесь TS, то чекайте на хороше й корисне оновлення. Воно напевне вдосконалить процес розробки ще більше, ніж теперішня версія. А якщо ви ще не знайомі з TS, то, можливо, саме настав час спробувати?
Ще немає коментарів