Топ ошибок начинающих TypeScript разработчиков: от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Топ ошибок начинающих TypeScript разработчиков: от А до Я

TypeScript — это мощный инструмент, который помогает писать более надежный и предсказуемый код. Однако на старте многие разработчики (особенно те, кто пришел из JavaScript) совершают типичные ошибки. В этой статье мы разберем 10 самых распространенных проблем, с которыми сталкиваются новички, и покажем, как их избежать. Погружаемся в мир TypeScript от А до Я.

1. Чрезмерное использование any

Это, пожалуй, самая популярная ошибка. Когда разработчик не знает, какой тип данных ожидать, он пишет any. Это убивает всю суть TypeScript — статическую типизацию. Вы теряете подсказки редактора и защиту от ошибок во время компиляции.

Плохой пример:

function processData(data: any) {
    return data.name.toLowerCase(); // Ошибка появится только в рантайме
}

Как исправить: Используйте более конкретные типы, unknown или дженерики.

function processData(data: { name: string }) {
    return data.name.toLowerCase(); // TypeScript проверит это на этапе компиляции
}

Если тип действительно неизвестен, используйте unknown — он заставит вас проверить данные перед использованием.

2. Игнорирование strict-режима

Многие начинающие отключают strict: true в tsconfig.json, чтобы "не было лишних ошибок". Это большая ошибка. Без strict-режима вы теряете проверку на null и undefined, что приводит к Cannot read property of undefined в продакшене.

// Без strict: true — ошибки нет
const name: string = null; // Работает, но потом упадет

// Со strict: true — ошибка компиляции
const name: string = null; // ❌ Type 'null' is not assignable to type 'string'

Совет: Всегда включайте strict: true. Это спасет вас от сотен багов.

3. Неправильное использование типов и интерфейсов

Новички часто путают type и interface, а также используют их там, где это не нужно. Например, создают интерфейс для одной функции, хотя можно просто описать тип прямо в параметре.

Плохой пример:

interface UserData {
    name: string;
    age: number;
}
function greet(user: UserData) {
    console.log(`Hello, ${user.name}`);
}

Это избыточно, если интерфейс используется только один раз.

Как лучше:

function greet(user: { name: string; age: number }) {
    console.log(`Hello, ${user.name}`);
}

Используйте interface для объектов, которые расширяются или реализуются классами, а type — для объединений (union) и пересечений (intersection).

4. Забывание про Union Types

Одна из самых мощных фич TypeScript — объединения типов. Новички часто пишут избыточные проверки или используют any, когда можно просто указать несколько допустимых типов.

// Плохо
function getLength(value: any) {
    return value.length;
}

// Хорошо
function getLength(value: string | any[]) {
    return value.length;
}

TypeScript сам подскажет, какие методы доступны для каждого из типов в объединении.

5. Ошибки с null и undefined

TypeScript строго относится к null и undefined, но новички часто забывают их проверять. Это приводит к ошибкам в рантайме.

function printName(name: string | null) {
    console.log(name.toUpperCase()); // ❌ Object is possibly 'null'
}

Как исправить: Используйте защитные проверки (type guards):

function printName(name: string | null) {
    if (name !== null) {
        console.log(name.toUpperCase()); // ✅ TypeScript знает, что name — это string
    }
}

Также полезен оператор ?. (optional chaining) и ?? (nullish coalescing).

6. Игнорирование дженериков (Generics)

Когда нужно написать функцию, работающую с разными типами, новички часто используют any или создают несколько дублирующих функций. Дженерики решают эту проблему элегантно.

// Плохо
function firstElement(arr: any[]) {
    return arr[0];
}

// Хорошо
function firstElement<T>(arr: T[]): T | undefined {
    return arr[0];
}

const num = firstElement([1, 2, 3]); // Тип: number | undefined
const str = firstElement(['a', 'b']); // Тип: string | undefined

Дженерики сохраняют информацию о типе и делают код переиспользуемым.

7. Неправильная работа с массивами

Путаница между Array<T> и T[] — это нормально, но проблема в том, что новички забывают указывать тип элементов массива.

// Плохо
const items = []; // Тип: never[] — ничего нельзя добавить
items.push('hello'); // ❌ Argument of type 'string' is not assignable to parameter of type 'never'

// Хорошо
const items: string[] = [];
items.push('hello'); // ✅

Всегда аннотируйте тип пустого массива, иначе TypeScript выведет never[].

8. Использование as для каста типов без проверки

Оператор as (type assertion) часто используется, чтобы "заставить" TypeScript поверить, что значение имеет определенный тип. Это опасно, если вы не уверены в данных.

const input = document.getElementById('input') as HTMLInputElement;
// Если элемента нет, input будет null, но TypeScript думает, что это HTMLInputElement
input.value = 'test'; // ❌ Ошибка в рантайме, если элемента нет

Как безопасно:

const input = document.getElementById('input');
if (input instanceof HTMLInputElement) {
    input.value = 'test'; // ✅ Безопасно
}

Используйте as только когда вы на 100%

Блоги

Рекомендаций по книгам