Пошук уроків, статей та іншого контенту
Створите короткі імпорти за допомогою baseUrl і paths та налаштуєте їх узгоджено з середовищем запуску.
baseUrl і pathsУ невеликих проєктах імпорти часто виглядають так:
import { formatPrice } from "../../../shared/utils/formatPrice";Такі імпорти складно читати й підтримувати. Якщо файл перемістити в іншу директорію, кілька рівнів ../ можуть стати неправильними.
TypeScript дає змогу налаштувати короткі імпорти за допомогою:
baseUrl — базової директорії для пошуку модулів;
paths — псевдонімів, які скорочують шляхи до файлів.
Наприклад:
import { formatPrice } from "@/shared/utils/formatPrice";baseUrlПрипустімо, структура проєкту має такий вигляд:
project/
├── src/
│ ├── app.ts
│ └── shared/
│ └── utils/
│ └── formatPrice.ts
└── tsconfig.jsonУ tsconfig.json можна вказати:
{
"compilerOptions": {
"baseUrl": "."
},
"include": ["src"]
}Значення "." означає кореневу директорію проєкту — директорію, у якій розташований tsconfig.json.
Після цього TypeScript зможе шукати модулі відносно кореня проєкту:
import { formatPrice } from "src/shared/utils/formatPrice";Однак такий запис усе ще містить структуру директорій. Для зручніших імпортів використовують paths.
pathspaths створює псевдоніми для шляхів:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"]
}Тепер TypeScript сприймає імпорт:
import { formatPrice } from "@/shared/utils/formatPrice";як шлях:
src/shared/utils/formatPrice"@/*": ["src/*"]@/* — шаблон, який використовуватиметься в імпорті;
* — довільна частина шляху;
src/* — шлях, якому відповідає ця частина.
Наприклад:
@/components/Buttonвідповідає:
src/components/ButtonМожна використовувати кілька псевдонімів:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@utils/*": ["src/shared/utils/*"]
}
}
}Тоді імпорти можуть виглядати так:
import { Button } from "@components/Button";
import { formatPrice } from "@utils/formatPrice";
import { apiClient } from "@/api/client";На практиці часто достатньо одного псевдоніма @/*. Надмірна кількість псевдонімів може ускладнити конфігурацію.
Структура проєкту:
project/
├── src/
│ ├── app.ts
│ └── shared/
│ └── utils/
│ └── formatPrice.ts
├── package.json
└── tsconfig.jsonФайл src/shared/utils/formatPrice.ts:
export function formatPrice(value: number, currency = "₴"): string {
return `${value.toFixed(2)} ${currency}`;
}Файл src/app.ts:
import { formatPrice } from "@/shared/utils/formatPrice";
const price = formatPrice(199.9);
console.log(price);Файл tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"]
}Для запуску цього прикладу через tsx можна використати такий package.json:
{
"private": true,
"scripts": {
"typecheck": "tsc --noEmit",
"start": "tsx src/app.ts"
},
"devDependencies": {
"tsx": "^4.0.0",
"typescript": "^5.0.0"
}
}Після встановлення залежностей:
npm install
npm run typecheck
npm startПрограма виведе:
199.90 ₴tsx у цьому прикладі читає псевдонім із tsconfig.json і використовує його під час запуску.
pathsНалаштування paths впливає на розуміння імпортів TypeScript, але саме по собі не змінює імпорти під час виконання програми.
Наприклад, TypeScript може правильно перевірити цей код:
import { formatPrice } from "@/shared/utils/formatPrice";Але після компіляції імпорт може залишитися таким самим:
import { formatPrice } from "@/shared/utils/formatPrice";Середовище запуску — Node.js, браузер або бандлер — повинно також знати, що означає @.
Тому псевдонім потрібно налаштувати узгоджено у двох місцях:
у tsconfig.json — для TypeScript;
у середовищі запуску або бандлері — для фактичного пошуку файлів.
У tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}А середовище запуску налаштоване на псевдонім $:
import { formatPrice } from "$/shared/utils/formatPrice";TypeScript не зможе правильно перевірити такий імпорт, бо псевдонім $ не описаний у paths.
Або TypeScript може знати про @, але середовище запуску не матиме відповідного налаштування. У такому разі перевірка типів завершиться успішно, але програма не запуститься.
tsconfig.jsonДеякі інструменти запуску TypeScript, зокрема tsx, можуть використовувати псевдоніми з tsconfig.json.
У такому випадку достатньо:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}і імпорту:
import { formatPrice } from "@/shared/utils/formatPrice";Проте перед використанням конкретного інструмента варто перевірити, чи підтримує він paths.
Якщо код збирає бандлер, йому також потрібно передати відповідність псевдоніма реальній директорії.
Наприклад, у конфігурації Vite можна вказати:
import { defineConfig } from "vite";
import path from "node:path";
export default defineConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "src")
}
}
});Це налаштування відповідає запису в tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}Обидва конфіги описують одне й те саме правило:
@/* → src/*baseUrlЗначення baseUrl потрібно визначати відносно розташування tsconfig.json.
Якщо конфігурація лежить у корені проєкту:
project/
├── src/
└── tsconfig.jsonвикористовують:
{
"compilerOptions": {
"baseUrl": "."
}
}Якщо конфігурація лежить у директорії config:
project/
├── config/
│ └── tsconfig.json
└── src/то шлях потрібно розраховувати вже від config.
У більшості проєктів основний tsconfig.json розміщують у корені. Це спрощує налаштування baseUrl і paths.
tsconfig.jsonTypeScript не показує помилок, але програма не запускається:
Cannot find module '@/shared/utils/formatPrice'Причина: середовище запуску не знає про псевдонім.
Потрібно налаштувати той самий псевдонім у бандлері або інструменті запуску.
pathsНаприклад:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/app/*"]
}
}
}А файл розташований у:
src/shared/utils/formatPrice.tsІмпорт:
import { formatPrice } from "@/shared/utils/formatPrice";шукатиме файл у:
src/app/shared/utils/formatPriceПравильна конфігурація:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}*Неправильно:
{
"compilerOptions": {
"paths": {
"@": ["src"]
}
}
}Такий запис описує лише точний імпорт @, а не вкладені шляхи.
Для імпортів на кшталт @/utils/helper потрібні шаблони:
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}У конфігурації:
{
"compilerOptions": {
"paths": {
"@/*": ["src/*"]
}
}
}А в коді:
import { helper } from "#/utils/helper";Псевдоніми # і @ — різні. Потрібно або змінити імпорт:
import { helper } from "@/utils/helper";або додати окремий псевдонім у конфігурацію.
tsconfig.json, який не застосовуєтьсяУ проєкті можуть бути кілька конфігурацій:
tsconfig.json
tsconfig.app.json
tsconfig.test.jsonЯкщо команда перевірки використовує tsconfig.app.json, а paths додано лише до іншого файлу, налаштування не спрацює.
Потрібно перевірити, який конфігураційний файл використовує команда tsc.
Визначайте baseUrl відносно кореня проєкту.
Починайте з одного зрозумілого псевдоніма, наприклад @/*.
Переконайтеся, що paths підтримує не лише редактор і TypeScript, а й середовище запуску.
Зберігайте однакове правило псевдоніма в tsconfig.json і конфігурації бандлера або рантайму.
Після зміни paths перезапустіть сервер розробки та TypeScript Server у редакторі, якщо він не підхопив зміни автоматично.
Не використовуйте псевдоніми для дуже коротких або неочевидних позначень, значення яких складно зрозуміти з імпорту.
baseUrl визначає базову директорію для пошуку модулів.
paths створює короткі псевдоніми для імпортів.
Запис "@/*": ["src/*"] перетворює @/utils/helper на src/utils/helper.
paths допомагає TypeScript аналізувати код, але не завжди налаштовує фактичний запуск програми.
Псевдоніми потрібно узгодити з бандлером або інструментом запуску.
Найчастіше зручно використовувати baseUrl: "." і один псевдонім "@/*": ["src/*"].