Есть ли дополнительные функции у TypeScript?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Дополнительные функции TypeScript сверх типизации
Многие думают, что TypeScript - это "просто JavaScript с типами". На самом деле, TypeScript предоставляет множество функций, которые НЕ доступны в обычном JavaScript. Давайте разберемся подробно.
1. Декораторы (Decorators)
Декораторы - это функции, которые могут модифицировать классы и их члены.
// Используй decorators для логирования
function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Вызов метода ${propertyKey} с аргументами:`, args);
return originalMethod.apply(this, args);
};
return descriptor;
}
class Calculator {
@Log
add(a: number, b: number): number {
return a + b;
}
}
const calc = new Calculator();
calc.add(2, 3); // Логирует: Вызов метода add с аргументами: [2, 3]
Декораторы очень полезны для:
- Логирования
- Кеширования
- Валидации
- Dependency injection
// Валидация данных с декоратором
function Min(min: number) {
return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalSetter = descriptor.set;
descriptor.set = function(value: number) {
if (value < min) {
throw new Error(`${propertyKey} не может быть меньше ${min}`);
}
originalSetter?.call(this, value);
};
return descriptor;
};
}
class User {
@Min(18)
age: number = 0;
}
2. Интерфейсы (Interfaces)
Интерфейсы - это контракты, которые классы должны выполнить.
interface Animal {
name: string;
age: number;
makeSound(): void;
}
class Dog implements Animal {
name: string;
age: number;
makeSound() {
console.log('Woof!');
}
}
// В JavaScript нет встроенного способа сделать это
// TypeScript гарантирует, что Dog реализует все методы Animal
3. Абстрактные классы (Abstract Classes)
abstract class Animal {
abstract makeSound(): void; // Наследники ДОЛЖНЫ реализовать
move(): void {
console.log('Moving...');
}
}
class Dog extends Animal {
makeSound() {
console.log('Woof!');
}
}
class Cat extends Animal {
makeSound() {
console.log('Meow!');
}
}
// const animal = new Animal(); // ОШИБКА: нельзя создать экземпляр абстрактного класса
const dog = new Dog(); // OK
4. Generics (обобщения)
Generics позволяют писать переиспользуемый код с типами.
// Без generics - нужны разные функции
function getFirstString(arr: string[]): string {
return arr[0];
}
function getFirstNumber(arr: number[]): number {
return arr[0];
}
// С generics - одна функция для всех типов
function getFirst<T>(arr: T[]): T {
return arr[0];
}
const firstString = getFirst(['a', 'b', 'c']); // тип: string
const firstNumber = getFirst([1, 2, 3]); // тип: number
Generics очень мощны для типобезопасности:
interface ApiResponse<T> {
status: number;
data: T;
error?: string;
}
async function fetchUser(id: string): Promise<ApiResponse<User>> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
async function fetchPosts(userId: string): Promise<ApiResponse<Post[]>> {
const response = await fetch(`/api/users/${userId}/posts`);
return response.json();
}
// TypeScript знает точный тип в каждом случае
5. Утилиты типов (Utility Types)
TypeScript предоставляет встроенные утилиты для манипуляции типами.
interface User {
id: string;
name: string;
email: string;
age: number;
}
// Partial - все поля опциональны
type PartialUser = Partial<User>;
const update: PartialUser = { name: 'John' }; // OK
// Required - все поля обязательны
type RequiredUser = Required<PartialUser>;
// const user: RequiredUser = { name: 'John' }; // ОШИБКА: нужны все поля
// Readonly - все поля read-only
type ReadonlyUser = Readonly<User>;
const user: ReadonlyUser = { /* ... */ };
// user.name = 'Jane'; // ОШИБКА: Cannot assign to 'name'
// Pick - выбрать только нужные поля
type UserPreview = Pick<User, 'id' | 'name'>;
const preview: UserPreview = { id: '1', name: 'John' }; // OK
// Omit - исключить ненужные поля
type UserWithoutEmail = Omit<User, 'email'>;
const user2: UserWithoutEmail = { id: '1', name: 'John', age: 30 }; // OK
// Record - создать объект с определёнными ключами
type Status = 'pending' | 'completed' | 'failed';
type StatusMessages = Record<Status, string>;
const messages: StatusMessages = {
pending: 'Ожидание...',
completed: 'Готово',
failed: 'Ошибка'
};
6. Условные типы (Conditional Types)
// Тип зависит от условия
type IsString<T> = T extends string ? true : false;
type A = IsString<'hello'>; // true
type B = IsString<42>; // false
// Более практичный пример
type Flatten<T> = T extends Array<infer U> ? U : T;
type Str = Flatten<string[]>; // string
type Num = Flatten<number>; // number
7. Mapped Types
// Преобразовать свойства типа
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface Person {
name: string;
age: number;
}
type PersonGetters = Getters<Person>;
// {
// getName: () => string;
// getAge: () => number;
// }
8. Type guards и сужение типов (Type Narrowing)
function processValue(value: string | number) {
// Type guard
if (typeof value === 'string') {
return value.toUpperCase(); // TypeScript знает, что это string
} else {
return value * 2; // TypeScript знает, что это number
}
}
// Пользовательский type guard
function isUser(obj: unknown): obj is User {
return (
typeof obj === 'object' &&
obj !== null &&
'id' in obj &&
'name' in obj
);
}
const data: unknown = fetchData();
if (isUser(data)) {
console.log(data.name); // OK - TypeScript знает, что это User
}
9. Перегрузка функций (Function Overloading)
// Одна функция может работать по-разному в зависимости от аргументов
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: number | string, b: number | string) {
if (typeof a === 'string' || typeof b === 'string') {
return String(a) + String(b);
}
return a + b;
}
add(1, 2); // 3 (number)
add('hello', ' world'); // "hello world" (string)
10. Namespace и Module System
// Организация кода в namespaces
namespace Math {
export const PI = 3.14159;
export function circumference(radius: number) {
return 2 * PI * radius;
}
}
const c = Math.circumference(5);
// Или современный способ с modules
export interface Config { /* ... */ }
export type Status = 'ok' | 'error';
export class Logger { /* ... */ }
export function log(msg: string) { /* ... */ }
11. Enum
// Enum - перечисление значений
enum Direction {
Up = 1,
Down = 2,
Left = 3,
Right = 4
}
const direction: Direction = Direction.Up;
// String enum
enum UserRole {
Admin = 'ADMIN',
User = 'USER',
Guest = 'GUEST'
}
const role: UserRole = UserRole.Admin;
// JavaScript не имеет встроенных enums
12. Типизация this
class User {
name: string = 'John';
// this имеет тип User
greet(this: User) {
console.log(`Hello, ${this.name}`);
}
// this может быть другого типа
chain(this: void): void {
// this недоступен
}
}
Преимущества этих функций
- Безопасность - типы ловят ошибки на этапе разработки
- Документация - код самодокументируется
- IDE поддержка - лучше автодополнение и рефакторинг
- Масштабируемость - проще работать в большых проектах
- Производительность - можешь оптимизировать на основе типов
Заключение
TypeScript - это не просто "JavaScript с типами". Это полноценный язык программирования с собственными концепциями:
- Декораторы
- Абстрактные классы и интерфейсы
- Generics
- Условные и mapped типы
- Type guards
- Перегрузка функций
- Enum и многое другое
Эти функции делают TypeScript мощным инструментом для разработки больших, надежных приложений.