20 приемов TypeScript, которые должен знать каждый разработчик

20 приемов TypeScript, которые должен знать каждый разработчик

TypeScript — это мощный инструмент для современной JavaScript-разработки, обеспечивающий типобезопасность и предоставляющий расширенные возможности.

Многие разработчики знают основы TypeScript, но знание некоторых приемов может сделать ваш код более эффективным, чистым и поддерживаемым. Давайте рассмотрим эти премы!

1. NonNullable

TypeScript предоставляет утилиту NonNullable для исключения null и undefined из типа. Это поможет вам избежать неожиданных нулевых значений.

type User = { name: string; age?: number | null };
const user: NonNullable<User["age"]> = 30; // ✅ No null or undefined allowed

2. Использование Partial для гибкости

Утилита Partial<T> делает все свойства типа необязательными. Это очень удобно, когда вы обновляете только подмножество полей объекта.

interface User {
  name: string;
  age: number;
  email: string;
}

const updateUser = (user: Partial<User>) => {
  // You can pass only the fields you want to update
  return { ...user, updatedAt: new Date() };
};

updateUser({ name: 'John' }); // No need to provide the entire object

3. Использование Readonly для неизменяемых данных

Если вам нужна неизменяемость в TypeScript, Readonly<T> сделает все свойства типа неизменяемыми, предотвращая переприсваивание.

const config: Readonly<{ apiUrl: string; retries: number }> = {
  apiUrl: 'https://api.example.com',
  retries: 5
};

config.apiUrl = 'https://newapi.com'; // ❌ Error: Cannot assign to 'apiUrl' because it is a read-only property

4. Сопоставленные типы для динамической типизации свойств

Сопоставленные типы позволяют создавать новые типы путем преобразования существующих. Это удобно для создания вариаций типа объекта.

type Status = 'loading' | 'success' | 'error';
type ApiResponse<T> = {
  [K in Status]: T;
};

const response: ApiResponse<string> = {
  loading: 'Fetching...',
  success: 'Data loaded',
  error: 'Something went wrong'
};

5. Типы кортежей с опциональными элементами

Знаете ли вы, что TypeScript позволяет использовать опциональные элементы в кортежах? Это очень удобно при работе с переменными аргументами функций.

type UserTuple = [string, number?, boolean?];

const user1: UserTuple = ['Alice'];          // ✅ Just the name
const user2: UserTuple = ['Bob', 30];        // ✅ Name and age
const user3: UserTuple = ['Charlie', 25, true]; // ✅ Full tuple

6. Union-типы с исчерпывающими проверками

Убедитесь, что вы обрабатываете все возможные случаи с помощью union-типов и исчерпывающих проверок в инструкциях switch.

type Status = 'open' | 'closed' | 'pending';

function handleStatus(status: Status) {
  switch (status) {
    case 'open':
      return 'Opened';
    case 'closed':
      return 'Closed';
    case 'pending':
      return 'Pending';
    default:
      const exhaustiveCheck: never = status; // ❌ Error if a new status type is added but not handled
      return exhaustiveCheck;
  }
}

7. Тип Omit для исключения ключей

Иногда вам нужно создать тип объекта, исключающий определенные ключи. В этом случае Omit — ваш друг!

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Omit<Todo, 'description'>;

const todo: TodoPreview = {
  title: 'Learn TypeScript',
  completed: false
};

8. Сужение типов с помощью in и instanceof

Используйте in и instanceof для сужения типов во время выполнения программы.

function processInput(input: string | number | { title: string }) {
  if (typeof input === 'string') {
    return input.toUpperCase(); // Narrowed to string
  } else if (typeof input === 'number') {
    return input * 2; // Narrowed to number
  } else if ('title' in input) {
    return input.title; // Narrowed to object with title property
  }
}

9. Условные типы для расширенной логики типов

Условные типы обеспечивают невероятную гибкость при преобразовании типов на основе условий.

type IsString<T> = T extends string ? true : false;

type CheckString = IsString<'Hello'>; // true
type CheckNumber = IsString<42>; // false

10. Использование as const для неизменяемых литеральных типов

as const отлично подходит для замораживания значений и обеспечения того, чтобы TypeScript рассматривал их как литеральные типы, а не как изменяемые значения.

const COLORS = ['red', 'green', 'blue'] as const;

type Color = typeof COLORS[number]; // 'red' | 'green' | 'blue'

11. Extract и Exclude для уточнения типов

Используйте Extract и Exclude, чтобы отфильтровать или выбрать определенные типы из объединения.

type T = 'a' | 'b' | 'c';
type OnlyAOrB = Extract<T, 'a' | 'b'>; // 'a' | 'b'
type ExcludeC = Exclude<T, 'c'>; // 'a' | 'b'

12. Защитники типа для пользовательской проверки

Создавайте собственных защитников типов (type guards) для динамического уточнения типов во время выполнения.

function isString(input: any): input is string {
  return typeof input === 'string';
}

const value: any = 'Hello';

if (isString(value)) {
  console.log(value.toUpperCase()); // Safe: value is a string here
}

13. Использование Record для типов динамических объектов

Когда вам нужен тип для объекта с динамическими ключами, Record<K, V> — идеальный вариант.

type Role = 'admin' | 'user' | 'guest';
const permissions: Record<Role, string[]> = {
  admin: ['read', 'write', 'delete'],
  user: ['read', 'write'],
  guest: ['read']
};

14. Динамические свойства классов с индексными сигнатурами

Индексные сигнатуры позволяют создавать объекты или классы с динамически именуемыми свойствами.

class DynamicObject {
  [key: string]: any;
}

const obj = new DynamicObject();
obj.name = 'Alice';
obj.age = 30;

15. Тип never для невозможных состояний

Тип never представляет значения, которые никогда не должны встречаться. Он часто используется в исчерпывающих проверках.

function assertNever(value: never): never {
  throw new Error(`Unexpected value: ${value}`);
}

16. Опциональные цепочки для безопасного доступа к свойствам

Используйте оператор опциональной последовательности (?.) для безопасного доступа к глубоко вложенным свойствам. Это позволит не опасаться ошибок, связанных с undefined.

const user = { profile: { name: 'John' } };
const userName = user?.profile?.name; // 'John'
const age = user?.profile?.age ?? 'Not provided'; // Fallback to default

17. Установка значений по умолчанию с помощью оператора нулевого слияния (??)

Используйте оператор нулевого слияния, чтобы предоставить запасное значение в том случае, если исходное значение равно null или undefined.

const input: string | null = null;
const defaultValue = input ?? 'Default'; // 'Default'

18. Вывод типов возвращаемых значений с помощью ReturnType

Утилита ReturnType<T> извлекает тип возвращаемого значения функции. Это может быть полезно, когда вы имеете дело со сложными типами.

function getUser() {
  return { name: 'John', age: 30 };
}

type UserReturn = ReturnType<typeof getUser>; // { name: string; age: number; }

19. Параметры типов в функциях

Параметры дженерик-типов делают ваши функции гибкими и пригодными для повторного использования в различных типах.

function identity<T>(value: T): T {
  return value;
}

identity<string>('Hello'); // 'Hello'
identity<number>(42); // 42

20. Типы пересечения для объединения структур

Типы пересечения (intersection types) позволяют объединять несколько типов в один.

type Admin = { privileges: string[] };
type User = { name: string };

type AdminUser = Admin & User;

const adminUser: AdminUser = {
  privileges: ['admin', 'editor'],
  name: 'Alice'
};

Эти приемы помогут вам поднять ваши навыки работы с TypeScript на новый уровень! Продолжайте экспериментировать и внедрять эти паттерны в свои проекты, чтобы код был чище и эффективнее. Успешного кодинга!

Перевод статьи “20 TypeScript Tricks Every Developer Should Know”.

Запись 20 приемов TypeScript, которые должен знать каждый разработчик впервые появилась techrocks.ru.

Наш сайт без рекламы для Вашего удобства! Чтобы поддержать проект – поделитесь ссылкой с друзьями. Благодарим!

Дмитрий

mirtayna.ru

Автор Цифрового контента.

Читать дальше

ПредыдущийСледующий
Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии