TypeScript 4.4: Хороший, Поганий і Не такий вже й поганий

9 хв. читання

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. Вони можуть застосовуватися до всього, від назв параметрів до отриманих типів повернення.

TypeScript 4.4: Хороший, Поганий і Не такий вже й поганий

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

TypeScript 4.4: Хороший, Поганий і Не такий вже й поганий

Спробуймо?

Імовірно, вам вже кортить скористатись усіма цими чудовими можливостями. Найкраще було б дочекатися стабільного випуску ще кілька тижнів. Тоді вам не доведеться мати справу з нерозв'язаними помилками та іншими проблемами.

Однак, якщо ви хочете спробувати версію RC зараз, то можете отримати її за допомогою NPM:

npm install typescript@rc

Потім, за потреби, виберіть її для користування у своєму IDE чи редакторі коду.

Природно, що у VS Code ви отримаєте найкращу якість роботи, а у VS Code Insiders ви отримаєте найновішу версію TS у комплекті.

Підсумуймо

Ну, нарешті! У TS 4.4 з'явиться безліч нововведень, а заплановано їх ще більше. Якщо ви користуєтесь TS, то чекайте на хороше й корисне оновлення. Воно напевне вдосконалить процес розробки ще більше, ніж теперішня версія. А якщо ви ще не знайомі з TS, то, можливо, саме настав час спробувати?

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.6K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація