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

TypeScript — это мощный инструмент для современной JavaScript-разработки, обеспечивающий типобезопасность и предоставляющий расширенные возможности.
Многие разработчики знают основы TypeScript, но знание некоторых приемов может сделать ваш код более эффективным, чистым и поддерживаемым. Давайте рассмотрим эти премы!
1. NonNullable
TypeScript предоставляет утилиту NonNullable
для исключения null
и undefined
из типа. Это поможет вам избежать неожиданных нулевых значений.
type User = { name: string; age?: number | null }; const user: NonNullable= 30; // No null or undefined allowed
2. Использование Partial для гибкости
Утилита Partial
делает все свойства типа необязательными. Это очень удобно, когда вы обновляете только подмножество полей объекта.
interface User { name: string; age: number; email: string; } const updateUser = (user: Partial) => { // 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
сделает все свойства типа неизменяемыми, предотвращая переприсваивание.
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= { [K in Status]: T; }; const response: ApiResponse = { 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; 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 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; // 'a' | 'b' type ExcludeC = Exclude ; // '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
— идеальный вариант.
type Role = 'admin' | 'user' | 'guest'; const permissions: Record= { 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
извлекает тип возвращаемого значения функции. Это может быть полезно, когда вы имеете дело со сложными типами.
function getUser() { return { name: 'John', age: 30 }; } type UserReturn = ReturnType; // { name: string; age: number; }
19. Параметры типов в функциях
Параметры дженерик-типов делают ваши функции гибкими и пригодными для повторного использования в различных типах.
function identity(value: T): T { return value; } identity ('Hello'); // 'Hello' identity (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.