Введение
TypeScript — это язык программирования общего назначения, используемый в различных средах разработки. За годы, прошедшие с момента его выпуска, он приобрёл широкую поддержку разработчиков и компаний, о чём свидетельствует рейтинг GitHub, который в 2022 году занял четвёртое место среди наиболее используемых языков программирования. С тех пор популярность TypeScript только росла.
Более того, его популярность отражается в обилии возможностей трудоустройства: на LinkedIn размещено более 20 000 вакансий, связанных с TypeScript, а крупнейшие игроки отрасли, включая Trivago и Stripe, решают перенести свои технологические стеки на TypeScript.
В этой статье мы рассмотрим TypeScript с самого начала, чтобы понять его преимущества, которые привели к его все более широкому использованию в сообществе разработчиков.
TypeScript против JavaScript
TypeScript не является чем-то совершенно новым. Это надмножество JavaScript, устраняющее ограничения самого JavaScript. Будучи надмножеством, TypeScript расширяет JavaScript, добавляя статическую типизацию.
Эту статическую типизацию можно объявить двумя распространёнными способами:
1.Введите аннотации
Это подразумевает немедленное указание переменных и их типов при их первом объявлении. Например:
let name: string = "HygraphГде name — имя переменной, а string — ее тип.
2. Псевдонимы типов
Этот метод предполагает отдельное определение типа с помощью ключевого слова type и последующее его использование для аннотации переменных.
type StringType = {
name: string;
};
let name: StringType = { name: "Hygraph" };Теперь давайте рассмотрим некоторые возможности, которые предлагает TypeScript.
Основные возможности TypeScript
Статическая типизация
Статическая типизация означает, что переменные явно объявляются с их типами данных (например, целочисленными, строковыми, логическими) во время компиляции, и система выполняет проверку типов перед выполнением программы.
Хотя следующее поведение разрешено в JavaScript, выполнение того же самого в TypeScript приведет к ошибке из-за реализации типа TypeScript.
let name: string = "hygraph";
name = 2000Необязательный ввод текста
Хотя TypeScript допускает явное объявление переменных, он также поддерживает написание JavaScript-подобного кода без объявления типов. TypeScript автоматически выводит тип. Например,
let name = "Hygraph";Выше TypeScript определяет, что имя типа представляет собой строку, через значение инициализации переменной, например, “Hygraph”.
Generics TypeScript
Параметризуя типы и функции, дженерики TypeScript создают повторно используемые компоненты и функции, которые могут работать с различными типами без ущерба для безопасности типов:
// Generic function to return the length of an array
function getArrayLength<T>(array: T[]): number {
return array.length;
}
// Using the generic function with different types of arrays
const stringArray: string[] = ["apple", "banana", "orange"];
const numberArray: number[] = [1, 2, 3, 4, 5];
console.log(getArrayLength(stringArray)); // Output: 3
console.log(getArrayLength(numberArray)); // Output: 5Дженерики обычно полезны для определения пользовательских типов данных, которые должны работать с такими типами данных, как деревья, графы и очереди.
Расширенная система типов
Система типов TypeScript выходит за рамки базовой статической типизации. Она также предоставляет функции для определения сложных типов, манипулирования типами, установления связей между переменными, применения ограничений типов и другие возможности, обеспечивающие безошибочную разработку приложений.
Давайте рассмотрим некоторые из наиболее широко используемых продвинутых типов.
1. Виды союзов
Объединение в TypeScript означает объявление переменной или аргумента функции, содержащего данные нескольких типов. Это может быть полезно, когда значение имеет разные типы данных во время выполнения.
Объединенные типы данных обозначаются символом «|», который разделяет типы данных. Например:
let age = number | string;
age = 10;
age = "ten";Как видно выше, мы можем указать, что переменная age может иметь два типа данных. Это обеспечивает гибкость без ущерба для типобезопасности.
2. Типы перекрестков
Кроссоверы позволяют создать новый тип путём объединения нескольких существующих типов. Этот новый тип обладает свойствами и функциями объединённых типов.
Пересечения создаются с помощью символа & между объединяемыми типами. Например:
interface User {
id: number;
username: string;
email: string;
}
interface Admin {
isAdmin: boolean;
}
// A new type using intersection type
type UserAndAdmin = User & Admin;Здесь тип User AndAdmin объединяет функции как пользовательского интерфейса, так и администрирования, создавая тип, требующий всех функций обоих.
3. Условные типы
Условные типы в TypeScript создают типы, зависящие от состояния, что позволяет определять динамические типы, которые изменяются в зависимости от свойств типа, значений или другого контекста.
Давайте рассмотрим простой пример:
// A conditional type to determine if a type is an array
type IsArray<T> = T extends any[] ? true : false;
// Test the conditional type with different types
type Result1 = IsArray<number>; // false
type Result2 = IsArray<string[]>; // true
type Result3 = IsArray<boolean | []>; // trueУсловные типы определяются с помощью тернарного оператора (? 🙂) в угловых скобках (<>), известного как “параметр обобщенного типа” — мы подробнее поговорим о нём далее в статье. Они также используют ключевое слово extends, которое проверяет, соответствует ли тип определённому условию, и создаёт другой тип на основе результата этого условия.
4. Типы сопоставлений
Сопоставленные типы в TypeScript позволяют создавать новые типы путём преобразования свойств существующих типов. Это достигается путём итерации по свойствам исходного типа и применения преобразования к каждому свойству для создания нового типа. Например:
// type representing a user
type User = {
id: number;
username: string;
email: string;
};
// Mapped type to make all properties optional
type OptionalUser = { [P in keyof User]?: User[P] };
// New type using the mapped type
const optionalUser: OptionalUser = { id: 1 };
// Property 'email' is now optional
optionalUser.username = "john_doe";
// Property 'id' is still required
// optionalUser.email = "[email protected]"; // Error: Property 'email' is missingСопоставленные типы определяются с помощью синтаксиса { [P in keyof Type]: NewType }, где Type — исходный тип, P — ключ свойства, а NewType — преобразованный тип. P выполняет итерацию по ключам свойств и определяет преобразование.
5. Введите псевдоним.
Псевдонимы типов позволяют создавать собственные имена (псевдонимы) для существующих типов TypeScript, включая примитивы, типы объединений, типы пересечений и даже более сложные типы, такие как объектные литералы и типы функций. Псевдоним типа определяется с помощью ключевого слова type, за которым следует новое имя, как показано ниже:
// type alias for a union type
type Result = "success" | "error";
// type alias for an object literal
type Point = { x: number; y: number };
// type alias for a function type
type Greeting = (name: string) => string;
// Using the type aliases
const status: Result = "success";
const origin: Point = { x: 0, y: 0 };
const greet: Greeting = (name) => Hello, ${name}!;Приведенный выше код демонстрирует различные варианты использования псевдонимов типов для разных типов в TypeScript и их использование после объявления.
TypeScript в объектно-ориентированном программировании (ООП)
ООП — это парадигма, основанная на концепции “объектов”, которые взаимодействуют для создания поддерживаемого и повторно используемого кода.
1. Классы TypeScript
Классы — это шаблоны или конструкции для создания объектов, то есть они определяют данные (свойства) и методы (функции).
Вот пример реализации класса в TypeScript:
class Organization {
private name: string;
private yearFounded: number;
constructor(name: string, yearFounded: number) {
this.name = name;
this.yearFounded = yearFounded;
}
public getDetails(): string {
return `${this.name} was founded in ${this.yearFounded}.`;
}
}
let organization = new Organization("Hygraph", 2015);
console.log(organization.name); // Error: Property 'name' is private and only accessible within class 'Organization'.
console.log(organization.getDetails()); // Output: Hygraph was founded in 2015В коде выше мы создали класс “Organization” с закрытыми свойствами «name» и «yearFounded», доступ к которым и их изменение возможны только внутри класса «Organization». Обратите внимание на типизацию свойств и методов.
2. Интерфейс TypeScript
Интерфейсы описывают форму объектов, перечисляя свойства и методы, которые они должны иметь, не предоставляя подробностей реализации:
// Interface representing form data
interface FormData {
firstName: string;
lastName: string;
email: string;
age: number;
}
// Usage
let formData: FormData = {
firstName: "John",
lastName: "Doe",
email: "[email protected]",
age: 30
};В приведенном выше примере мы определили интерфейс FormData, который представляет структуру данных формы.
Затем мы создали объект formData со свойствами, связанными с определением интерфейса.
Номера TypeScript
Перечислимые типы, представленные в TypeScript как enum, представляют собой набор именованных констант, заключенных в фигурные скобки {}, где каждая константа имеет связанное числовое или строковое значение.
Типичная коллекция списков TypeScript может выглядеть так:
// enum for days of the week
enum DayOfWeek {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
enum HTTPStatusCodes {
OK = 200,
BadRequest = 400,
NotFound = 404,
}Приведенный выше блок кода сразу же объясняет происходящее и демонстрирует семантическое преимущество добавления смысла в использование перечислений TypeScript.
TypeScript и ES6
TypeScript поддерживает многие функции ECMAScript 6 (ES6), также известного как ECMAScript 2015. Некоторые из этих функций включают в себя:
1) Стрелочные функции: В отличие от традиционных функциональных выражений, стрелочные функции предоставляют простой синтаксис для определения функций. Они обеспечивают неявный возврат для однострочных выражений и автоматическое объединение в цепочки, а также могут быть полезны для функций обратного вызова или обработчиков событий.
// Arrow function
const add = (x, y) => x + y;
// Traditional function expression
const add = function(x, y) {
return x + y;
};2) Шаблонный алфавит: позволяет встраивать многострочные выражения и строки непосредственно в код в фигурных скобках (“). Это упрощает создание динамических строк, включая интерполяцию переменных и выражений.
const name: string = "John";
const greeting: string = `Hello, ${name}!`;Возможностей ES6 гораздо больше, чем можно описать в этой статье. Подробнее см. на сайте Ecma International.
Преимущества TypeScript перед JavaScript
С момента появления TypeScript более десяти лет назад не утихают споры о его преимуществах перед JavaScript.
В этом разделе мы рассмотрим некоторые из этих преимуществ.
- Тип безопасности: Статическая система типов TypeScript применяет аннотации типов к переменным, функциям и объектам, что помогает обнаруживать ошибки на ранних стадиях и повышает удобство поддержки благодаря интерфейсам, классам и модулям.
- Лучший опыт разработчика: Теперь разработчики могут писать код с большей уверенностью, зная, что компилятор обнаружит потенциальные несоответствия типов ещё до того, как код будет запущен. Это может быть особенно полезно при переносе кодовой базы JavaScript на TypeScript.
Когда использовать TypeScript
Из рассмотренных выше компромиссов можно сделать вывод, что TypeScript может подойти не для всех проектов. Возможно, это правда, но зачем оставлять этот выбор на ваше усмотрение? Позвольте нам помочь вам принять более взвешенное решение.
Когда целесообразно использовать TypeScript?
- Крупномасштабные приложения: TypeScript был разработан для решения проблем масштабируемости больших баз кода JavaScript. По мере роста проекта статическая типизация помогает выявлять ошибки на ранних этапах, улучшая поддержку кода и взаимодействие между членами команды.
- Командная работа: В командной среде, где несколько разработчиков вносят свой вклад в кодовую базу, TypeScript может облегчить совместную работу, обеспечивая соблюдение соглашений о кодировании и улучшая коммуникацию посредством самодокументируемого кода.
- Долгосрочные проекты: Сопровождение — это последний этап жизненного цикла разработки программного обеспечения, который может длиться от десятилетия до года. TypeScript подходит для долгосрочных проектов, где удобство поддержки кода, масштабируемость и готовность к будущему являются важнейшими факторами.
Когда не следует использовать TypeScript
К сожалению, несмотря на свои преимущества, TypeScript может не подходить для всех случаев использования. Например:
- Простые проекты: Для небольших проектов с минимальной сложностью преимущества статической типизации и расширенного инструментария могут не перевесить затраты на настройку и обучение, связанные с TypeScript.
- Старые кодовые базы: Конвертация больших существующих кодовых баз JavaScript в TypeScript может быть непростой задачей. В таких случаях усилия, необходимые для перехода на TypeScript, могут не оправдать получаемые преимущества, особенно если проект подходит к концу или находится на минимальном обслуживании.









