@types
DefinitelyTyped, npm @types, установка и использование
📖 Введение
Представьте, что вы приходите в магазин электроники. Вы хотите купить телефон, но не знаете его характеристик. Вам нужен каталог, который описывает все модели: какие функции есть, какой размер экрана, какой объём памяти. Без каталога вы не сможете выбрать подходящий телефон.
@types — это такой каталог для JavaScript-библиотек. Это пакеты типов, которые описывают API существующих библиотек. Они хранятся в репозитории DefinitelyTyped и устанавливаются через npm.
Например, вы хотите использовать lodash в TypeScript-проекте. Сами типы уже написаны — просто установите пакет @types/lodash, и TypeScript сразу будет знать типы всех функций.
1 Что такое DefinitelyTyped — репозиторий типов
DefinitelyTyped (github.com/DefinitelyTyped/DefinitelyTyped) — это крупнейший репозиторий типов для JavaScript-библиотек. Он содержит тысячи пакетов типов для популярных библиотек:
@types/lodash— типы для Lodash@types/express— типы для Express.js@types/react— типы для React@types/node— типы для Node.js API@types/jest— типы для Jest@types/jquery— типы для jQuery@types/mocha— типы для Mocha@types/chai— типы для Chai
Важно: Начиная с TypeScript 4.7, многие библиотеки включают типы внутри себя (в пакете). Например, axios уже содержит index.d.ts. В таких случаях @types/axios не нужен.
2 Установка @types — npm install
Установка пакетов типов выполняется через npm:
# Установка типов для lodash
npm install --save-dev @types/lodash
# Установка типов для Express
npm install --save-dev @types/express
# Установка типов для Node.js
npm install --save-dev @types/node
# Установка типов для Jest
npm install --save-dev @types/jest
# Установка нескольких пакетов сразу
npm install --save-dev @types/lodash @types/express @types/node
Обратите внимание: типы устанавливаются как --save-dev — это dev-зависимости, потому что они нужны только при разработке, а не в продакшене.
После установки TypeScript автоматически находит типы в node_modules/@types:
import _ from 'lodash';
import express from 'express';
// TypeScript теперь знает типы!
const numbers = [1, 2, 3, 4, 5];
const doubled = _.map(numbers, (n) => n * 2); // number[]
const app = express();
app.get('/', (req, res) => { // req: Request, res: Response
res.send('Привет, мир!');
});
3 Как проверить наличие типов —три типа способа
Есть три способа проверить, есть ли типы для библиотеки:
1. Проверить пакет на npmjs.com:
Зайдите на npmjs.com/package/имя_пакета и посмотрите в поле «Types» или «typings». Если там есть путь — типы встроены.
2. Проверить в npm search:
# Искать @types пакет
npm search @types/lodash
# Или проверить, установлен ли уже
npm list @types/lodash
# Проверить, содержит ли пакет встроенные типы
npm info lodash types
3. Посмотреть в DefinitelyTyped:
Зайдите на github.com/DefinitelyTyped/DefinitelyTyped и найдите папку с именем вашей библиотеки.
4 Когда @types не нужен — встроенные типы
Многие современные библиотеки включают типы внутри себя. В таких случаях отдельный пакет @types не нужен:
axios— уже содержит типыdate-fns— уже содержит типыzod— уже содержит типыreact— уже содержит типыvue— уже содержит типыtypescript— уже содержит типы
Как проверить: Посмотрите в node_modules/имя_пакета. Если там есть index.d.ts или поле "types" в package.json — типы встроены.
5 Создание своего @types пакета — для внутренних библиотек
Если вы пишете собственную библиотеку на JavaScript и хотите предоставить типы для TypeScript-пользователей, создайте @types пакет:
# Создайте папку для типов
mkdir my-lib-types
cd my-lib-types
# Инициализируйте npm-проект
npm init -y
Отредактируйте package.json:
{
"name": "@types/my-lib",
"version": "1.0.0",
"description": "Types for my-lib",
"main": "index.d.ts",
"types": "index.d.ts",
"license": "MIT",
"dependencies": {}
}
Создайте index.d.ts:
// index.d.ts
export function greet(name: string): string;
export function add(a: number, b: number): number;
export interface Config {
apiUrl: string;
timeout: number;
debug: boolean;
}
export class Logger {
constructor(prefix: string);
log(message: string): void;
warn(message: string): void;
error(message: string): void;
}
6 Отправка в DefinitelyTyped — PR в репозиторий
Если вы хотите, чтобы типы стали доступны всем через npm install @types/ваша_библиотека, создайте Pull Request в DefinitelyTyped:
# Клонируйте DefinitelyTyped
git clone https://github.com/DefinitelyTyped/DefinitelyTyped.git
# Создайте папку для ваших типов
mkdir types/your-lib
# Создайте файл your-lib/index.d.ts
# Создайте файл your-lib/your-lib-tests.ts (тесты типов)
# Создайте файл your-lib/tsconfig.json
Пример тестового файла:
// your-lib-tests.ts
import { greet, add, Logger } from 'your-lib';
// Проверяем, что функции работают с правильными типами
const message: string = greet('Мир'); // ✅ string
const sum: number = add(1, 2); // ✅ number
// Проверяем, что ошибки типов ловятся
const wrong: string = add('1', '2'); // ❌ Ошибка типа
const logger = new Logger('App');
logger.log('Привет'); // ✅
DefinitelyTyped автоматически тестирует типы. Если тесты проходят, PR будет смержен и типы станут доступны всем.
⚙️ Настройка TypeScript для @types
TypeScript автоматически находит типы в node_modules/@types. Но вы можете настроить это в tsconfig.json:
{
"compilerOptions": {
// Папки, где искать типы
"typeRoots": [
"./node_modules/@types",
"./src/types"
],
// Какие пакеты типов подключать автоматически
// Если не указано — подключаются ВСЕ из typeRoots
"types": [
"node",
"jest",
"lodash",
"express"
]
}
}
Важно: Если вы указали types, TypeScript будет подключать только указанные пакеты. Если types не указан — подключаются все из typeRoots.
7 Решение проблем с типами — типичные ошибки и решения
Вот типичные проблемы, с которыми сталкиваются при работе с @types:
1. «Could not find a declaration file for module 'xxx'»
// Решение: установите @types пакет
npm install --save-dev @types/имя_пакета
// Или создайте свой .d.ts файл
// custom.d.ts
declare module 'имя_пакета' {
export function someFunction(arg: string): void;
}
2. Типы не обновляются после установки @types
# Решение: очистите кэш TypeScript
rm -rf node_modules/.cache
rm -rf node_modules/@types
npm install
3. Конфликт типов — «Duplicate identifier»
# Решение: проверьте, нет ли дублирующих @types пакетов
npm list @types/имя_пакета
# Если есть — удалите дубликат
npm uninstall @types/имя_пакета
8 Best practices — лучшие практики работы с @types
Следуйте этим рекомендациям при работе с @types:
- Всегда проверяйте, содержит ли библиотека встроенные типы перед установкой @types
- Устанавливайте @types как dev-зависимости (--save-dev)
- Регулярно обновляйте @types пакеты — типы могут устареть
- Используйте
skipLibCheck: trueв tsconfig.json, если типы конфликтуют - Для кастомных библиотек создавайте собственные .d.ts файлы
- Проверяйте наличие типов на npmjs.com перед установкой пакета
✅ Итого
- DefinitelyTyped — крупнейший репозиторий типов для JavaScript-библиотек
- @types — пакеты типов, устанавливаемые через npm
- Установка:
npm install --save-dev @types/имя_библиотеки - Многие современные библиотеки уже содержат типы внутри себя — @types не нужен
- TypeScript автоматически находит типы в
node_modules/@types - Настройка:
typeRootsиtypesв tsconfig.json - Для собственных библиотек создавайте @types пакеты или добавляйте .d.ts файлы
9 Версионирование @types — совместимость версий
@types пакеты имеют свои версии, которые должны совпадать с версиями библиотек:
# Если библиотека установлена версии 4.17.0
npm install lodash@4.17.0
# Установите @types версии 4.17.x
npm install --save-dev @types/lodash@4.17
Если версии не совпадают, TypeScript может показывать ошибки или предупреждения. Используйте npm ls для проверки:
# Проверить установленные версии
npm ls lodash @types/lodash
# Результат:
# my-project@1.0.0
# ├── lodash@4.17.21
# └── @types/lodash@4.17.0 ✅
10 @types и Node.js — типизация Node.js API
@types/node — один из самых важных @types пакетов. Он описывает API Node.js:
// Установка
npm install --save-dev @types/node
// Теперь TypeScript знает API Node.js
import * as fs from 'fs';
import * as path from 'path';
// fs — TypeScript знает все функции
const content: string = fs.readFileSync('./file.txt', 'utf-8');
// path — TypeScript знает все функции
const fullPath: string = path.join(__dirname, 'data', 'file.txt');
// process — TypeScript знает свойства
const env: string | undefined = process.env.NODE_ENV;
const args: string[] = process.argv;
Без @types/node TypeScript не знает о Node.js API и будет показывать ошибки.
11 @types и Webpack — типизация конфигурации
Webpack также имеет @types пакет для типизации конфигурации:
# Установка
npm install --save-dev @types/webpack
// webpack.config.ts
import { Configuration } from 'webpack';
const config: Configuration = {
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
};
export default config;
12 @types и Express — типизация сервера
Express.js — популярный фреймворк для Node.js. @types/express описывает его API:
# Установка
npm install --save-dev @types/express @types/node
// server.ts
import express, { Request, Response, NextFunction } from 'express';
const app = express();
// TypeScript знает типы req и res
app.get('/api/users', (req: Request, res: Response) => {
const users = [
{ id: 1, name: 'Алексей' },
{ id: 2, name: 'Мария' }
];
res.json(users);
});
app.post('/api/users', (req: Request, res: Response) => {
const { name } = req.body; // ✅ req.body типизирован
res.status(201).json({ id: 3, name });
});
// Middleware с правильными типами
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
res.status(500).json({ error: 'Что-то пошло не так' });
});
app.listen(3000, () => {
console.log('Сервер запущен на порту 3000');
});
13 @types и Mongoose — типизация MongoDB
Mongoose — ODM для MongoDB. Его типы позволяют работать с MongoDB с полной типизацией:
# Установка
npm install mongoose @types/mongoose
// models/User.ts
import { Schema, model, Document } from 'mongoose';
interface IUser {
name: string;
email: string;
age: number;
createdAt: Date;
}
// Документ Mongoose расширяет IUser
interface IUserDocument extends IUser, Document {}
const userSchema = new Schema<IUserDocument>({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
age: { type: Number, required: true },
createdAt: { type: Date, default: Date.now }
});
export const User = model<IUserDocument>('User', userSchema);
// Использование:
async function createUser(name: string, email: string, age: number) {
const user = new User({ name, email, age });
await user.save(); // ✅ TypeScript знает типы
return user;
}
14 @types и Jest — типизация тестов
Jest — популярный тестовый фреймворк. @types/jest описывает его API:
# Установка
npm install --save-dev jest ts-jest @types/jest
// utils.test.ts
import { add, formatDate } from './utils';
describe('Math functions', () => {
it('should add two numbers correctly', () => {
expect(add(1, 2)).toBe(3);
expect(add(-1, 1)).toBe(0);
expect(add(0, 0)).toBe(0);
});
});
describe('Date functions', () => {
it('should format date correctly', () => {
const date = new Date('2024-01-15');
expect(formatDate(date)).toBe('15.01.2024');
});
});
// Мокирование
describe('API calls', () => {
it('should fetch data', async () => {
const mockFetch = jest.fn().mockResolvedValue({ data: 'test' });
global.fetch = mockFetch;
const result = await fetch('/api/data');
expect(result).toEqual({ data: 'test' });
expect(mockFetch).toHaveBeenCalledWith('/api/data');
});
});
15 @types и Lodash — типизация утилит
Lodash — популярная утилитарная библиотека. @types/lodash описывает её API:
# Установка
npm install lodash @types/lodash
// Использование
import _ from 'lodash';
const numbers = [1, 2, 3, 4, 5];
// TypeScript знает типы всех функций
const doubled = _.map(numbers, (n) => n * 2); // number[]
const filtered = _.filter(numbers, (n) => n > 2); // number[]
const sum = _.reduce(numbers, (acc, n) => acc + n, 0); // number
// Удобные утилиты
const unique = _.uniq([1, 1, 2, 3, 3]); // number[]
const chunked = _.chunk([1, 2, 3, 4, 5], 2); // number[][]
const flattened = _.flatten([[1, 2], [3, 4], [5]]); // number[]
// Объекты
const user = { name: 'Алексей', age: 25, email: 'alex@example.com' };
const picked = _.pick(user, ['name', 'email']); // { name: string; email: string }
const omitted = _.omit(user, ['age']); // { name: string; email: string }
16 @types и GraphQL — типизация API
GraphQL — язык запросов для API. @types/graphql описывает его типы:
# Установка
npm install graphql @types/graphql
// schema.ts
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLList
} from 'graphql';
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: GraphQLInt },
name: { type: GraphQLString },
email: { type: GraphQLString }
}
});
const QueryType = new GraphQLObjectType({
name: 'Query',
fields: {
user: {
type: UserType,
args: {
id: { type: GraphQLInt }
},
resolve: (_, { id }) => {
return { id, name: 'Алексей', email: 'alex@example.com' };
}
}
}
});
const schema = new GraphQLSchema({
query: QueryType
});
17 @types и Socket.IO — типизация WebSocket
Socket.IO — библиотека для WebSocket. @types/socket.io описывает его API:
# Установка
npm install socket.io @types/socket.io
// server.ts
import { Server } from 'socket.io';
const io = new Server(3000, {
cors: {
origin: 'http://localhost:5173'
}
});
// TypeScript знает типы событий
io.on('connection', (socket) => {
console.log('Пользователь подключился:', socket.id);
// Обработка событий
socket.on('message', (data: { text: string; user: string }) => {
console.log(`${data.user}: ${data.text}`);
io.emit('message', data);
});
socket.on('disconnect', () => {
console.log('Пользователь отключился:', socket.id);
});
});
Клиентская часть:
// client.ts
import { io } from 'socket.io-client';
const socket = io('http://localhost:3000');
// Отправка сообщения
socket.emit('message', { text: 'Привет!', user: 'Алексей' });
// Получение сообщения
socket.on('message', (data: { text: string; user: string }) => {
console.log(`${data.user}: ${data.text}`);
});
Socket.IO обеспечивает надёжную связь между клиентом и сервером в реальном времени.
Проверяем понимание
5 вопросов