- Главная
- Typescript
- Анатомия типов в Typescript — аннотации, примитивы и литералы
Анатомия типов в Typescript — аннотации, примитивы и литералы
В прошлых уроках мы установили TypeScript, научились его настраивать и поняли, зачем он нужен. Сегодня мы переходим к самому сердцу языка — его синтаксису. Я покажу вам, как с помощью аннотаций типов превратить ваш JavaScript-код в строго типизированный и предсказуемый.
TypeScript — это надстройка над JavaScript, и его синтаксис интуитивно понятен любому, кто уже знаком с JS. Главное нововведение — это возможность явно указывать типы данных для переменных, параметров функций и возвращаемых значений.
Аннотации типов для переменных
Аннотация типа (краткое описание) ставится после имени переменной через двоеточие. Это ваш первый шаг к строгой типизации.
let username: string = "Alice";
let age: number = 30;
let isActive: boolean = true;
let id: number | string = "abc123"; // Union Type — об этом позже
Теперь, если вы попытаетесь присвоить переменной username число, TypeScript выдаст ошибку ещё до того, как код запустится:
username = 42; // ❌ Ошибка: Type 'number' is not assignable to type 'string'
Это называется строгой типизацией. В обычном JavaScript вы бы узнали об ошибке только во время выполнения, а TypeScript ловит её на этапе написания кода.
Примитивные типы: основа основ
TypeScript использует те же примитивные типы, что и JavaScript, но добавляет к ним строгость:
number— любые числа: целые, дробные, отрицательные,Infinity,NaN.string— текстовые строки в одинарных, двойных или обратных кавычках.boolean—trueилиfalse.
null и undefined — тоже типы, но при включённом strictNullChecks (а мы его включили во втором уроке) вы не сможете просто так присвоить их переменным других типов.
let city: string = "Moscow";
city = null; // ❌ Ошибка при strictNullChecks
Литеральные типы: точность до значения
Более тонкая настройка — это литеральные типы. Они позволяют указать не просто «строка», а конкретную строку или конкретное число.
let status: "success" = "success"; // Только это значение
// status = "failure"; // ❌ Ошибка
let direction: "up" | "down" | "left" | "right"; // Union с литералами
direction = "up"; // ✅
direction = "north"; // ❌ Ошибка
Литеральные типы особенно полезны в комбинации с объединениями (Union Types), о которых мы поговорим в следующем уроке.
Аннотации для функций
Функции — это главное место, где аннотации типов приносят наибольшую пользу. Мы можем указать типы для каждого параметра и тип возвращаемого значения.
function greet(name: string): string {
return `Hello, ${name}!`;
}
function add(a: number, b: number): number {
return a + b;
}
function logMessage(message: string): void {
console.log(message); // void означает, что функция ничего не возвращает
}
Почему это важно? Когда вы видите сигнатуру функции, вы сразу понимаете, как её использовать:
// Ясно и понятно
function calculateDiscount(price: number, percent: number): number {
return price * (percent / 100);
}
// Вместо гаданий в JS
function calculateDiscount(price, percent) {
return price * (percent / 100);
}
TypeScript также следит, чтобы вы не забыли вернуть значение (если обещали) и не вернули что-то не то:
function getMessage(): string {
return 42; // ❌ Ошибка: Type 'number' is not assignable to type 'string'
}
Оживи свой сайт. Освой JavaScript!
Статичная верстка — это только скелет. Наш онлайн-курс "JavaScript с нуля до профи" даст твоим страницам мышцы и нервы. Научись создавать слайдеры, формы, интерактивные карты и получать данные с сервера.
От теории — к реальным скриптам в твоём портфолио.
Вывод типов (Type Inference)
Хорошая новость: вам не всегда нужно явно указывать типы. TypeScript умный и часто может вывести их сам.
let message = "Hello!"; // TypeScript выводит, что message — string
message = 42; // ❌ Ошибка: Type 'number' is not assignable to type 'string'
function multiply(a: number, b: number) {
return a * b; // TypeScript выводит, что возвращается number
}
Однако есть случаи, когда TypeScript не может вывести тип — тогда переменная получает тип any (что отключает проверку). В строгом режиме это запрещено, и вы обязаны указать тип явно:
let data; // ❌ Неявный any (если включен noImplicitAny)
data = "hello";
data = 42; // Ошибки не будет, потому что any разрешает всё
Тип any и почему его стоит избегать
any — это способ сказать TypeScript «отстань от меня, я знаю, что делаю». Но на самом деле это лишает вас всех преимуществ TypeScript.
let value: any = "hello";
value = 42;
value = true;
value.someNonExistentMethod(); // ✅ Нет ошибки, но в рантайме всё упадёт
Если вы используете any, вы возвращаетесь к уровню безопасности обычного JavaScript. Вместо any лучше использовать unknown (если вы действительно не знаете тип) или уточнять типы с помощью Type Guards.
Практическое упражнение
Давайте закрепим материал. Вот несколько примеров кода на JavaScript. Ваша задача — добавить к ним аннотации типов, используя изученный синтаксис.
// 1. Переменные
const productName = "Laptop";
const productPrice = 999.99;
const inStock = true;
// 2. Функция
function formatPrice(price, currency) {
return currency + price.toFixed(2);
}
// 3. Функция с разными типами параметров
function getLength(value) {
return value.length;
}
// 4. Функция без возврата
function showMessage(text) {
console.log(text);
}
Решение (не подглядывайте сразу):
// 1. Переменные
const productName: string = "Laptop";
const productPrice: number = 999.99;
const inStock: boolean = true;
// 2. Функция
function formatPrice(price: number, currency: string): string {
return currency + price.toFixed(2);
}
// 3. Функция с разными типами параметров
function getLength(value: string | any[]): number {
return value.length;
}
// 4. Функция без возврата
function showMessage(text: string): void {
console.log(text);
}
Обратите внимание: в третьей функции мы использовали Union Type (string | any[]), потому что длина есть и у строк, и у массивов. Это одна из мощных возможностей TypeScript, к которой мы перейдём в следующем уроке.
Type Aliases: даём имена типам
Перед тем как закончить урок, я хочу познакомить вас с очень полезной концепцией — Type Aliases (псевдонимы типов). Они позволяют дать имя любому типу и переиспользовать его.
// Вместо того чтобы писать это каждый раз
let userId: string | number = 123;
// Мы создаём псевдоним
type ID = string | number;
let userId: ID = 123;
let productId: ID = "abc";
// Это работает и для более сложных типов
type Status = "active" | "inactive" | "pending";
let userStatus: Status = "active";
Псевдонимы типов особенно полезны, когда один и тот же тип используется в разных частях программы. Они делают код чище и уменьшают дублирование.
Итог
Сегодня мы заложили фундамент синтаксиса TypeScript:
- Аннотации типов для переменных, параметров и возвращаемых значений (
: type). - Примитивные типы —
string,number,boolean,null,undefined. - Литеральные типы — конкретные значения строк или чисел.
- Тип
voidдля функций, которые ничего не возвращают. - Вывод типов — TypeScript часто понимает типы сам, но не всегда.
- Псевдонимы типов (
type) — даём имена сложным типам для переиспользования.
В следующем уроке мы углубимся в работу с массивами и объектами — структурами данных, с которыми вы работаете каждый день. Мы научимся описывать их форму и делать свойства опциональными. А затем перейдём к Union Types — мощному инструменту, который делает TypeScript по-настоящему гибким.