Типизация переменных и функций

Урок: Типизация переменных и функций в TypeScript

Введение

В прошлом уроке мы познакомились с базовыми типами: string, number, boolean, any. Теперь у нас есть «словарь» типов.

Но просто знать типы — недостаточно. Важно научиться применять их в коде: в переменных и функциях.

Представь, что ты пишешь функцию логина:

  • она принимает логин и пароль;
  • возвращает результат (успешно или нет).

Если не указать типы, легко перепутать:

  • передать число вместо строки;
  • забыть, что функция должна вернуть значение;
  • использовать результат неправильно.

Типизация помогает избежать этого.

Главная идея урока: мы учимся явно описывать, какие данные используются в переменных и как работают функции.


Типизация переменных

Ты уже видел базовый синтаксис:

const username: string = 'Alex';
const age: number = 25;
const isActive: boolean = true;

Здесь важно понять структуру: имяПеременной: тип = значение.

TypeScript проверяет:

  • соответствует ли значение типу;
  • не меняется ли тип позже.

Пример ошибки:

let score: number = 100;
// score = 'high'; // ошибка TS: string нельзя присвоить number
console.log('score:', score);

TypeScript не позволит «сломать» тип переменной.


Когда можно не указывать тип явно

TypeScript умеет сам определять тип:

const city = 'Helsinki';

Он понимает, что это string.

Но есть нюанс:

let loose;
loose = 10;
loose = 'text';

Здесь loose часто становится any, потому что:

  • тип не был указан;
  • TypeScript не смог его зафиксировать.

Поэтому правило:

  • если значение сразу понятно — можно не указывать тип;
  • если нет — лучше указать явно.

Типизация функций: зачем это нужно

Функции — это место, где ошибки происходят чаще всего.

Пример без типизации параметров (как в JavaScript):

function add(a, b) {
  return a + b;
}

add(2, 3); // 5
add('2', '3'); // "23"

JavaScript не знает, что ты хотел сложить числа.


Как типизировать параметры функции

В TypeScript ты явно указываешь тип каждого параметра:

function add(a: number, b: number): number {
  return a + b;
}

console.log('числа:', add(2, 3));
// add('2', '3'); // ошибка TS: аргументы должны быть number

Что здесь происходит:

  • a: number — первый параметр должен быть числом;
  • b: number — второй параметр тоже;
  • TypeScript проверяет вызовы функции.

Как работает типизация внутри функции

Типы параметров используются внутри функции.

function greet(name: string): string {
  return name.toUpperCase();
}

TypeScript «знает», что:

  • name — строка;
  • у строки есть метод toUpperCase().

Если бы тип был не указан или был any, такой проверки не было бы.


Типизация возвращаемого значения (введение)

TypeScript может сам понять, что возвращает функция:

function multiply(a: number, b: number) {
  return a * b;
}
console.log('произведение (TS вывел бы тип number):', multiply(3, 4));

Он определит, что результат — number.

Но ты также можешь указать это явно:

function multiplyTyped(a: number, b: number): number {
  return a * b;
}
console.log('явный контракт возврата : number →', multiplyTyped(2, 5));

Здесь:

  • : number после скобок — это тип возвращаемого значения.

Почему это важно — подробно разберём в следующем уроке.


Ошибки, которые предотвращает типизация функций

Рассмотрим пример:

function getUserName(id: number): string {
  return 'User';
}

const name = getUserName(1);
console.log(name.toUpperCase());

Если функция всегда возвращает строку — всё ок.

Но если ты случайно изменишь её:

function getUserNameBroken(id: number) {
  return 123;
}

const name2 = getUserNameBroken(1);
try {
  console.log((name2 as any).toUpperCase());
} catch (e: unknown) {
  const msg = e instanceof Error ? e.message : String(e);
  console.log('ошибка при вызове toUpperCase:', msg);
}

Если тип возвращаемого значения указан явно как string, такую ошибку поймают до запуска. Ниже — только рантайм-эффект на чистом JavaScript (без проверки типов):

function getUserName(id) {
  return 123;
}
console.log('в JS функция вернула число:', getUserName(1));

TypeScript поймает проблему раньше.


Частая ошибка новичков

Иногда хочется «обойти» систему:

function log(value: unknown) {
  console.log(value);
}
log('строка');
log(42);

Это работает, но:

  • для unknown внутри функции нужны сужения типа;
  • ошибки могут появиться позже, если везде использовать any.

Лучше делать так:

function logLabeled(label: string, value: string | number) {
  console.log(label + ':', value);
}
logLabeled('id', 1);
logLabeled('имя', 'Alex');

Чем точнее тип — тем надёжнее код.


Связь с дальнейшими уроками

Сейчас ты научился:

  • типизировать переменные;
  • задавать типы параметров функций;
  • понимать, как TypeScript проверяет код.

Дальше мы будем расширять это:

  • научимся работать с объектами и интерфейсами;
  • разберём возвращаемые значения функций подробнее;
  • применим всё это в Playwright.

Практическое применение

Типизация переменных и функций используется постоянно.

Пример из реальной задачи:

function login(username: string, password: string): boolean {
  if (username === 'admin' && password === '1234') {
    return true;
  }
  return false;
}
console.log('ok:', login('admin', '1234'));
console.log('fail:', login('admin', '0000'));

Здесь:

  • понятно, какие данные нужны;
  • понятно, что вернёт функция;
  • сложно использовать её неправильно.

Итоговое понимание

Типизация переменных и функций — это следующий шаг после знакомства с базовыми типами.

Ты не просто знаешь типы, а начинаешь управлять ими в коде:

  • фиксируешь, какие данные хранятся в переменных;
  • задаёшь, какие параметры принимает функция;
  • контролируешь, как используется результат.

Главная мысль:

TypeScript превращает функции и переменные из «гибких и непредсказуемых» в «понятные и контролируемые».

И именно это делает код более надёжным — особенно в больших проектах и тестах, к которым мы скоро перейдём.