← Назад к вопросам

Как указать в методе что должен прийти какой-либо тип?

1.0 Junior🔥 251 комментариев
#Node.js и JavaScript#TypeScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как указать тип параметра в методе

В Node.js есть несколько способов указывать типы параметров в методах. Выбор зависит от стека и требований проекта.

1. TypeScript (рекомендуемый подход)

Типичная современная практика в production-среде.

Базовые типы

// Примитивные типы
function greet(name: string, age: number, active: boolean): void {
  console.log(`${name} is ${age} years old`);
}

greet('Alice', 30, true);  // ✅ OK
greet('Bob', '25', true);  // ❌ Error: Argument of type 'string' is not assignable to parameter of type 'number'

Сложные типы

// Интерфейсы
interface User {
  id: number;
  name: string;
  email?: string;  // Опциональное поле
}

function createUser(user: User): User {
  return { ...user, id: Math.random() };
}

// Типы
type Status = 'active' | 'inactive' | 'pending';

function updateUserStatus(userId: number, status: Status): void {
  console.log(`User ${userId} status: ${status}`);
}

updateUserStatus(1, 'active');     // ✅ OK
updateUserStatus(1, 'unknown');    // ❌ Error: not assignable

Классы с типами

class UserService {
  createUser(user: User): Promise<User> {
    return Promise.resolve(user);
  }
  
  findById(id: number): User | null {
    // Может вернуть User или null
    return null;
  }
  
  getUsers(): User[] {
    return [];
  }
}

Обобщённые типы (Generics)

// Универсальная функция
function echo<T>(value: T): T {
  return value;
}

echo<string>('hello');    // Type: string
echo<number>(42);         // Type: number

// Обобщённый класс
class Repository<T> {
  private items: T[] = [];
  
  add(item: T): void {
    this.items.push(item);
  }
  
  getAll(): T[] {
    return this.items;
  }
}

const userRepo = new Repository<User>();
userRepo.add({ id: 1, name: 'Alice' });  // ✅ OK
userRepo.add('not a user');              // ❌ Error

Union Types

function process(value: string | number | boolean): void {
  if (typeof value === 'string') {
    console.log(value.toUpperCase());
  } else if (typeof value === 'number') {
    console.log(value * 2);
  }
}

process('hello');   // ✅ OK
process(42);        // ✅ OK
process(true);      // ✅ OK
process([]);        // ❌ Error

2. JSDoc в JavaScript (для legacy проектов)

Если проект всё ещё на чистом JavaScript, но хочешь типизацию.

/**
 * Создаёт пользователя
 * @param {Object} user - Объект пользователя
 * @param {number} user.id - ID пользователя
 * @param {string} user.name - Имя
 * @param {string} [user.email] - Email (опциональный)
 * @returns {Promise<Object>} Созданный пользователь
 */
async function createUser(user) {
  return await db.users.insert(user);
}

/**
 * Валидирует возраст
 * @param {number} age - Возраст пользователя
 * @returns {boolean} Валидный ли возраст
 */
function isValidAge(age) {
  return age >= 18 && age <= 120;
}

// IDE покажет типи, но runtime проверки нет

3. Runtime проверка типов (валидация)

Для Production важна не только типизация, но и runtime валидация.

С использованием Zod

import { z } from 'zod';

const UserSchema = z.object({
  id: z.number(),
  name: z.string().min(2).max(100),
  email: z.string().email(),
  age: z.number().min(0).max(150).optional(),
});

type User = z.infer<typeof UserSchema>;  // Автоматически из schema

function createUser(data: unknown): User {
  // Валидирует в runtime
  return UserSchema.parse(data);
  // Выбросит ошибку, если data не соответствует schema
}

createUser({ name: 'Alice', email: 'test@example.com' });  // ❌ id обязателен
createUser({ id: 1, name: 'Alice', email: 'test@example.com' });  // ✅ OK

С использованием Joi (для Express)

import Joi from 'joi';

const userSchema = Joi.object({
  id: Joi.number().required(),
  name: Joi.string().min(2).max(100).required(),
  email: Joi.string().email().required(),
});

app.post('/users', (req, res) => {
  const { error, value } = userSchema.validate(req.body);
  
  if (error) {
    return res.status(400).json({ error: error.details });
  }
  
  // value содержит валидные данные
  const user = createUser(value);
  res.json(user);
});

4. Class Validator (для NestJS/TypeORM)

import { IsString, IsEmail, IsNumber, IsOptional } from 'class-validator';

export class CreateUserDto {
  @IsNumber()
  id: number;
  
  @IsString()
  name: string;
  
  @IsEmail()
  email: string;
  
  @IsOptional()
  @IsNumber()
  age?: number;
}

// В контроллере
@Post('/users')
async create(@Body() createUserDto: CreateUserDto) {
  // Автоматически валидируется
  return this.userService.create(createUserDto);
}

5. Strict Mode в TypeScript

// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "noImplicitAny": true,
    "noImplicitThis": true
  }
}

Эти настройки принуждают тебя быть явным с типами:

// Без strict mode (опасно)
function process(value) {  // ❌ Неявный any
  return value.toUpperCase();  // Может упасть в runtime
}

// Со strict mode (безопасно)
function process(value: string): string {
  return value.toUpperCase();
}

Практический пример: полный сценарий

// schema.ts
import { z } from 'zod';

export const UserSchema = z.object({
  id: z.number(),
  name: z.string().min(2),
  email: z.string().email(),
});

export type User = z.infer<typeof UserSchema>;

// service.ts
class UserService {
  async createUser(data: unknown): Promise<User> {
    const validated = UserSchema.parse(data);  // Runtime валидация
    // Сохраняем в БД
    return validated;
  }
  
  async getUserById(id: number): Promise<User | null> {
    // Возвращает User или null (явная типизация)
    return null;
  }
}

// controller.ts
app.post('/users', async (req, res) => {
  try {
    const user = await userService.createUser(req.body);
    res.json(user);  // user: User (TypeScript знает структуру)
  } catch (error) {
    res.status(400).json({ error: 'Invalid user data' });
  }
});

Рекомендации

  1. Используй TypeScript для production-кода
  2. Strict mode: true в tsconfig.json
  3. Валидирование в runtime (Zod, Joi, class-validator)
  4. Типизируй всё явно — не полагайся на type inference
  5. Избегай any — используй unknown + type guard, если нужно
// ❌ Плохо
function process(value: any): any {
  return value.something();
}

// ✅ Хорошо
function process(value: unknown): string {
  if (typeof value === 'object' && value !== null && 'method' in value) {
    return value.method();
  }
  throw new Error('Invalid input');
}

Типизация в TypeScript — это не просто документация, это страховка для production-кода. Правильно типизированный код == меньше багов в production.