در یکی از پروژه‌های React که با تیم دیگری شروع شده بود، شش ماه بعد از تحویل با مشکلی عجیب روبرو شدیم: هر بار که یک افزونه‌ی کوچک نصب می‌کردیم، build چند دقیقه طول می‌کشید و TS خطاهای تازه‌ای می‌داد. بعد از بازبینی، فهمیدم که فایل tsconfig.json آن پروژه، تنظیمات پیش‌فرضی داشت که با ساختار واقعی پروژه هماهنگ نبود. هیچ‌کس به آن فایل نگاه نکرده بود. آن تجربه به من فهماند که tsconfig.json فقط یک فایل تنظیمات فنی نیست؛ یک بیانیه‌ی معماری از نحوه‌ی فکر کردن به پروژه است. از آن روز، اولین کاری که در بازبینی هر پروژه‌ی TS انجام می‌دهم، باز کردن tsconfig است.

فایل tsconfig.json قلب هر پروژه‌ی TypeScript است. این فایل تصمیم می‌گیرد که TypeScript چطور کد شما را کامپایل کند، چطور تایپ‌ها را بررسی کند و چه محدودیت‌هایی را اعمال کند. اگر در مسیر آموزش تایپ اسکریپت از صفر هستید و مقالات تایپ ها در تایپ اسکریپت و ماژول ها در تایپ اسکریپت را خوانده‌اید، این نوشته لایه‌ی زیربنایی همان مباحث را باز می‌کند.

چرا tsconfig.json یک تصمیم معماری است؟

تصور رایج این است که tsconfig فقط یک فایل پیکربندی است که باید در ابتدای پروژه ساخته شود و بعد فراموش شود. اما تجربه‌ی چندساله‌ی من نشان می‌دهد که این فایل، سه نقش معماری مهم ایفا می‌کند:

  • تعیین قرارداد محافظت: با فعال یا غیرفعال کردن strict mode، شما تصمیم می‌گیرید که چقدر می‌خواهید کامپایلر TS از شما محافظت کند. یک tsconfig ضعیف، تمام تایپ‌های شما را نیمه‌کاره می‌کند. مطالعه‌ی موازی این لایه در تفاوت تایپ اسکریپت و جاوااسکریپت آمده است.
  • تعریف استراتژی build: تنظیمات target و module مستقیماً روی خروجی نهایی، سرعت build و سازگاری با محیط اجرا اثر می‌گذارد. یک target اشتباه، باعث می‌شود که کد شما به JavaScript ناسازگار با مرورگر کاربر تبدیل شود.
  • تعیین ساختار پروژه: از طریق paths و include، شما مشخص می‌کنید که پروژه چه بخش‌هایی دارد و importها چطور مسیریابی می‌شوند. این یک تصمیم معماری است که در طول عمر پروژه، روی خوانایی و نگهداری اثر مستقیم دارد. مطالعه‌ی بیشتر در ماژول ها در تایپ اسکریپت.

قاعده‌ی من در پروژه‌ها: tsconfig را نه به‌عنوان یک فایل جانبی، بلکه به‌عنوان بخشی از معماری پروژه نگاه کنید. اگر tsconfig را درست طراحی کنید، کدبیس به‌طور طبیعی تمیزتر می‌شود. اگر آن را نادیده بگیرید، در طول عمر پروژه به یک منبع باگ تبدیل می‌شود.

tsconfig.json مثل قانون اساسی یک پروژه‌ی TypeScript است: اگر قانون، سست نوشته شود، همه‌ی ساختار بعدی روی همان سستی بنا می‌شود؛ اگر دقیق نوشته شود، ساختار با انضباط پیش می‌رود.

ساختار پایه و مفاهیم اولیه

هر فایل tsconfig.json با یک ساختار پایه شروع می‌شود:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

سه بخش اصلی در این ساختار:

  • compilerOptions: تنظیمات کامپایلر. این بخش تمام تصمیمات مربوط به نحوه‌ی کامپایل و تایپ‌چکینگ را نگه می‌دارد.
  • include: فایل‌هایی که باید کامپایل شوند.
  • exclude: فایل‌هایی که باید نادیده گرفته شوند.
  • extends: امکان ارث‌بری تنظیمات از یک tsconfig دیگر (در بخش جداگانه‌ای به آن می‌رسیم).
  • files: فهرست دقیق فایل‌ها (به‌جای الگو). در پروژه‌های معمولی به‌ندرت استفاده می‌شود.
  • references: برای پروژه‌های چندبخشی (monorepo). در پروژه‌های پیشرفته کاربرد دارد.

ساختن اولین tsconfig با دستور tsc --init انجام می‌شود که یک فایل پیش‌فرض با تمام گزینه‌ها و توضیحات تولید می‌کند. این یک نقطه‌ی شروع مفید است اما فایل پیش‌فرض هرگز برای پروژه‌ی واقعی کافی نیست.

target: زبان خروجی نهایی

تنظیم target تعیین می‌کند که کد TypeScript به چه نسخه‌ای از JavaScript کامپایل شود:

{
  "compilerOptions": {
    "target": "ES2020"
  }
}

مقادیر پرکاربرد:

targetکاربردخروجی
ES5پشتیبانی از مرورگرهای قدیمیکد verbosed، حجم بیشتر
ES2015 (ES6)پشتیبانی از مرورگرهای مدرن متوسطخروجی متعادل
ES2020مرورگرهای مدرنخروجی تمیز، حجم کمتر
ES2022مرورگرهای جدیدترکد بسیار شبیه به منبع
ESNextآخرین استانداردبدون transpile اضافه

نکته‌ی مهم: اگر از یک bundler مثل Vite یا Webpack استفاده می‌کنید، bundler خودش مسئول transpile نهایی است. در این حالت، target می‌تواند ESNext باشد چون کامپایلر TS فقط برای بررسی تایپ است و خروجی توسط bundler تولید می‌شود.

در پروژه‌ای که یک فروشگاه اینترنتی بود، با تغییر target از ES5 به ES2015، حجم bundle نهایی حدود ۱۸٪ کاهش پیدا کرد — فقط به‌دلیل حذف polyfillهای اضافی که برای ES5 تولید می‌شدند. این یک تصمیم ساده با اثر مستقیم است.

قاعده‌ی من در پروژه‌ها: اگر bundler دارید، ESNext را انتخاب کنید و بگذارید bundler transpile نهایی را برای مرورگرهای هدف انجام دهد. اگر خروجی را مستقیم برای Node.js یا مرورگر تولید می‌کنید، ES2020 انتخاب متعادلی است.

module و moduleResolution: نحوه‌ی مدیریت ماژول‌ها

دو تنظیم مهم در tsconfig که مستقیماً روی ساختار ماژول‌ها اثر می‌گذارند:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}

مقادیر مهم:

  • module: تعیین می‌کند که خروجی با چه سیستم ماژولی تولید شود. مقادیر پرکاربرد: CommonJS، ESNext، ES2020، NodeNext.
  • moduleResolution: الگوریتمی که برای پیدا کردن ماژول‌ها استفاده می‌شود. مقادیر پرکاربرد: node، node16، nodenext، bundler.

ترکیب‌های پیشنهادی بر اساس سناریو:

سناریوmodulemoduleResolution
پروژه React با ViteESNextbundler
پروژه Node.js مدرنNodeNextnodenext
پروژه Node.js قدیمیCommonJSnode
کتابخانه‌ی npmESNext + CommonJSbundler
پروژه SSR (Next.js)ESNextbundler

یک نکته‌ی ظریف که در پروژه‌ها به‌کارم آمده: اگر یک کتابخانه‌ی npm منتشر می‌کنید، معمولاً باید هم به ESM و هم به CommonJS خروجی بدهید. راه‌حل استاندارد: دو tsconfig با تنظیمات متفاوت، یکی برای هر فرمت. مطالعه‌ی بیشتر در ماژول ها در تایپ اسکریپت.

خانواده strict: قلب محافظت تایپ

مهم‌ترین تنظیم tsconfig، strict: true است:

{
  "compilerOptions": {
    "strict": true
  }
}

این یک تنظیم واحد است که در واقع چند تنظیم دیگر را با هم فعال می‌کند:

  • noImplicitAny: جلوگیری از any ضمنی وقتی تایپ مشخص نشده است.
  • strictNullChecks: null و undefined به‌عنوان تایپ‌های مستقل دیده می‌شوند.
  • strictFunctionTypes: بررسی دقیق‌تر سازگاری تایپ‌های توابع.
  • strictBindCallApply: بررسی دقیق‌تر روی bind، call و apply.
  • strictPropertyInitialization: تضمین مقداردهی اولیه‌ی تمام فیلدهای کلاس.
  • noImplicitThis: جلوگیری از this با تایپ ضمنی.
  • alwaysStrict: فعال‌سازی strict mode در خروجی JS.

در پروژه‌ای که یک تیم فنی روی یک پروژه‌ی موجود TS کار می‌کرد، فعال‌سازی strict: true روی کدبیسی که شش ماه با تنظیمات پیش‌فرض نوشته شده بود، حدود ۴۰۰ خطا را آشکار کرد. بسیاری از این خطاها باگ‌های بالقوه‌ای بودند که تا آن زمان پنهان مانده بودند. سه ماه طول کشید تا همه‌ی خطاها رفع شوند، اما بعد از آن، تعداد باگ‌های runtime به‌طور محسوسی کاهش پیدا کرد.

قاعده‌ی من در پروژه‌های جدید: از روز اول strict: true را فعال کنید. اگر پروژه‌ی موجود دارید و می‌خواهید به strict مهاجرت کنید، می‌توانید به‌صورت تدریجی با // @ts-strict کامنت روی فایل‌ها شروع کنید. مطالعه‌ی این لایه در چارچوب کارایی در تفاوت تایپ اسکریپت و جاوااسکریپت.

strict: true در TypeScript مثل کلید ایمنی در خودرو است: ممکن است در روز اول کمی آزاردهنده به‌نظر برسد، اما در روز حادثه، تفاوت بین یک پروژه‌ی سالم و یک باگ production را می‌سازد.

baseUrl و paths: مختصر کردن importها

یکی از پرکاربردترین تنظیمات tsconfig که بلافاصله خوانایی کد را بالا می‌برد:

{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@components/*": ["components/*"],
      "@utils/*": ["utils/*"],
      "@types/*": ["types/*"],
      "@api/*": ["api/*"]
    }
  }
}

با این تنظیمات، به‌جای importهای طولانی مثل:

import { Button } from "../../../components/ui/Button";

می‌توانید بنویسید:

import { Button } from "@components/ui/Button";

سه مزیت این الگو:

  1. خوانایی بالاتر: مسیر importها دیگر به عمق فایل بستگی ندارد. اگر فایل را جابه‌جا کنید، importها نمی‌شکنند.
  2. Refactoring ساده‌تر: تغییر ساختار پوشه‌ها فقط نیاز به تغییر در tsconfig دارد، نه در تمام فایل‌ها.
  3. مرزهای معماری واضح: مسیرهایی مثل @components و @api خودشان یک نقشه‌ی معماری از پروژه هستند.

نکته‌ی مهمی که در پروژه‌ها دیده‌ام: اگر مسیرهای Alias را در tsconfig تعریف کنید، باید آن‌ها را در bundler هم تنظیم کنید. در Vite با resolve.alias و در Webpack با resolve.alias. بعضی توسعه‌دهنده‌ها فراموش می‌کنند و بعد از تغییر tsconfig، در runtime خطای «module not found» می‌گیرند.

قاعده‌ی من در پروژه‌ها: حداکثر سه یا چهار Alias اصلی تعریف کنید. Aliasهای بی‌رویه، به‌جای ساده‌کردن، پیچیدگی اضافه می‌کنند. مطالعه‌ی بیشتر در ماژول ها در تایپ اسکریپت.

include، exclude و files

این سه تنظیم مشخص می‌کنند که TS چه فایل‌هایی را باید کامپایل کند:

{
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"],
  "files": ["src/main.ts"]
}

قواعد کلیدی:

  • include: الگوهای Glob. پیش‌فرض همه‌ی فایل‌های TS در پوشه‌ی tsconfig و زیرپوشه‌ها. معمولاً به src/**/* محدود می‌کنند.
  • exclude: الگوهایی که از include حذف می‌شوند. مهم: exclude فقط روی include اثر دارد، نه روی فایل‌هایی که با import وارد شده‌اند.
  • files: فهرست دقیق فایل‌ها. برخلاف include، الگو نمی‌پذیرد.

یک دام مهم که در پروژه‌ها دیده‌ام: بعضی توسعه‌دهنده‌ها فرض می‌کنند که exclude می‌تواند فایل‌های وابسته را هم حذف کند. اما اگر یک فایل از include وارد یک فایل دیگر شود، آن فایل حتی اگر در exclude باشد، کامپایل می‌شود. این رفتار باعث می‌شود که بعضی خطاهای تایپ از فایل‌هایی که انتظار ندارید بیاید.

extends و ارث‌بری تنظیمات

اگر روی چند پروژه کار می‌کنید یا یک monorepo دارید، extends یک ابزار قدرتمند است:

{
  "extends": "@tsconfig/strictest/tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist"
  }
}

با این تنظیم، تمام تنظیمات tsconfig پایه به ارث می‌رسد و می‌توانید فقط بخش‌های مورد نیاز را override کنید.

چند پکیج محبوب از @tsconfig:

  • @tsconfig/strictest — سخت‌گیرانه‌ترین تنظیمات ممکن.
  • @tsconfig/node20 — برای Node.js نسخه ۲۰.
  • @tsconfig/vite-react — برای پروژه‌های Vite + React.
  • @tsconfig/next — برای پروژه‌های Next.js.

در یک پروژه‌ی monorepo که شامل frontend، backend و shared بود، از extends برای تعریف یک tsconfig پایه استفاده کردیم و هر پکیج، فقط بخش‌های اختصاصی خودش را override می‌کرد. این الگو، هماهنگی تنظیمات در کل monorepo را تضمین می‌کرد و اجازه می‌داد که در زمان نیاز، یک پکیج بتواند رفتار متفاوتی داشته باشد. مطالعه‌ی موازی در توسعه وردپرس از صفر و ابزارهای CI/CD.

lib و types: مدیریت کتابخانه‌های خارجی

دو تنظیم مهم که در پروژه‌های واقعی اثر محسوسی دارند:

{
  "compilerOptions": {
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "types": ["node", "jest"]
  }
}

تفاوت این دو:

  • lib: کتابخانه‌های داخلی TS و APIهای بومی مرورگر یا Node.js. مثلاً DOM شامل تمام تایپ‌های مربوط به document، window، HTMLElement و غیره است.
  • types: تایپ‌های کتابخانه‌های خارجی که در node_modules/@types یا پکیج‌های داخلی قرار دارند.

یک اشتباه رایج: در پروژه‌های Node.js، فراموش کردن "lib": ["ES2020"] باعث می‌شود که TS تایپ‌های جدید زبان (مثل Promise.allSettled) را نشناسد. در پروژه‌های React، فراموش کردن DOM باعث خطاهای مربوط به document و window می‌شود.

قاعده‌ی من در پروژه‌ها: lib را بر اساس محیط اجرا تنظیم کنید. برای پروژه‌ی فرانت‌اند: ["ES2020", "DOM", "DOM.Iterable"]. برای پروژه‌ی Node.js: ["ES2020"]. برای کتابخانه: فقط ["ES2020"] چون کتابخانه نباید به APIهای مرورگر وابسته باشد. مطالعه‌ی بیشتر در تایپ اسکریپت با Node.js و تایپ اسکریپت با React.

سناریوهای React، Node و کتابخانه‌ها

در این بخش، تنظیمات پیشنهادی برای سه سناریوی رایج را می‌آورم:

پروژه‌ی React با Vite

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "jsx": "react-jsx",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "esModuleInterop": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "noEmit": true,
    "baseUrl": "./src",
    "paths": {
      "@/*": ["*"]
    }
  },
  "include": ["src"]
}

پروژه‌ی Node.js مدرن

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "nodenext",
    "strict": true,
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "sourceMap": true,
    "declaration": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

کتابخانه‌ی عمومی npm

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["**/*.test.ts", "**/*.spec.ts"]
}

نکته‌ی مهم در کتابخانه‌ها: تنظیم declaration: true باعث می‌شود که فایل‌های .d.ts در خروجی تولید شوند. بدون این فایل‌ها، کاربران TypeScript نمی‌توانند تایپ‌های کتابخانه‌ی شما را ببینند. این یک الزام در انتشار کتابخانه‌های عمومی است. مطالعه‌ی موازی در ماژول ها در تایپ اسکریپت.

اشتباهاتی که در پروژه‌ها دیدم

  • غیرفعال نگه‌داشتن strict: شایع‌ترین اشتباه. اگر strict را فعال نکنید، تایپ‌های TS نیمی از قدرتشان را از دست می‌دهند. رویکرد درست: از ابتدا فعال کنید یا مهاجرت تدریجی به strict را برنامه‌ریزی کنید.
  • نادیده گرفتن paths: importهای طولانی و مسیرهای نسبی پیچیده، خوانایی را پایین می‌آورند. اضافه کردن paths یک تصمیم کوچک با اثر بزرگ در بلندمدت است.
  • فراموش کردن تنظیمات در bundler: اگر paths را در tsconfig تعریف کنید اما در Vite یا Webpack تنظیم نکنید، در build به خطای «module not found» می‌خورید.
  • استفاده از target قدیمی با polyfillهای اضافه: اگر با bundler کار می‌کنید، ES5 انتخاب اشتباهی است. این کار حجم bundle را بالا می‌برد بدون هیچ سود واقعی.
  • نادیده گرفتن lib مناسب: در پروژه‌های Node.js، استفاده از ["ES2020", "DOM"] باعث می‌شود که TS به شما اجازه دهد از APIهای مرورگر در کد Node استفاده کنید، بدون هشدار. این یک بدهی پنهان است که در runtime خودش را نشان می‌دهد.
  • skipLibCheck غیرفعال: تنظیم skipLibCheck: true یک راه‌حل عالی برای کاهش زمان build است. غیرفعال نگه‌داشتن آن، در پروژه‌های بزرگ می‌تواند زمان build را چند برابر کند بدون سود محسوس.
  • نادیده گرفتن esModuleInterop: در پروژه‌های Node.js مدرن، این تنظیم برای سازگاری با کتابخانه‌های CommonJS ضروری است. بدون آن، ممکن است در importهای کتابخانه‌های خارجی خطا بگیرید.
  • نادیده گرفتن isolatedModules: اگر از bundlerهایی مثل esbuild یا SWC استفاده می‌کنید، isolatedModules: true یک محافظت ضروری است. این تنظیم شما را از کدهایی که در bundler سریع نمی‌توانند پردازش شوند، دور می‌کند.
  • declaration در کتابخانه‌ی عمومی: فراموش کردن declaration: true در کتابخانه‌های npm یعنی کاربران TS شما هیچ تایپی نمی‌بینند. این یک نکته‌ی کوچک است که در انتشار عمومی، تفاوت بزرگی می‌سازد.
  • تغییر تنظیمات بدون مستندسازی: در پروژه‌های تیمی، tsconfig باید در مستندات پروژه توضیح داده شود. اگر یک توسعه‌دهنده‌ی جدید دلیل یک تنظیم خاص را نداند، ممکن است به‌اشتباه آن را تغییر دهد.

بخشی از این اشتباهات در خطاهای رایج تایپ اسکریپت و اشتباهات رایج توسعه هم آمده است.

لایه‌ای زیر تنظیمات tsconfig

اینجا وارد لایه‌ای می‌شوم که در پروژه‌های معمولی به آن نگاه نمی‌شود اما برای مهندسان پلتفرم و توسعه‌دهنده‌های ارشد اهمیت دارد. آنچه کامپایلر TypeScript با تنظیمات شما انجام می‌دهد، در پنج مفهوم خلاصه می‌شود:

  1. Incremental Compilation و buildInfo: تنظیم incremental: true به TS اجازه می‌دهد که نتایج کامپایل قبلی را در فایلی به نام .tsbuildinfo نگه دارد و در buildهای بعدی، فقط فایل‌های تغییر‌یافته را دوباره بررسی کند. در پروژه‌های بزرگ، این یک صرفه‌جویی محسوس در زمان build است — مثلاً در پروژه‌ای با ۵۰۰ فایل TS، زمان build از ۴۵ ثانیه به ۶ ثانیه کاهش پیدا کرد. نکته: این فایل باید در .gitignore قرار بگیرد و در build pipeline هر بار ساخته شود. مطالعه‌ی موازی در ابزارهای CI/CD و گیت در وردپرس.
  2. Project References و Build Mode: در monorepoها، تنظیم references به شما اجازه می‌دهد که پروژه را به بخش‌های مستقل تقسیم کنید. هر بخش می‌تواند جداگانه build شود و TS می‌فهمد که کدام بخش‌ها به هم وابسته‌اند. با دستور tsc --build، فقط بخش‌های تغییر‌یافته و وابستگانش دوباره build می‌شوند. این ویژگی در پروژه‌های بزرگ با چند پکیج، تفاوت محسوسی در سرعت توسعه می‌سازد. مطالعه‌ی موازی در ماژول ها در تایپ اسکریپت و توسعه وردپرس از صفر.
  3. Custom Transformerها و Interaction با Bundler: در پروژه‌های مدرن، کامپایلر TS به‌تنهایی مسئول build نیست. ابزارهایی مثل esbuild، SWC و Babel با custom transformerها، مسئولیت transpile و build نهایی را به عهده می‌گیرند. تفاوت مهم: این ابزارها تایپ‌چکینگ انجام نمی‌دهند. یعنی باید tsc --noEmit را جداگانه در pipeline اجرا کنید. این نکته‌ی ظریف در پروژه‌ای که فقط به esbuild اتکا کرده بود، باعث شد چند خطای تایپ در production پیدا شود. مطالعه‌ی موازی این لایه در بهینه سازی جاوااسکریپت و بهینه‌سازی سرعت سایت آمده است.
  4. Type Checking در Mode جداگانه: در پروژه‌های مدرن، جدا کردن فاز تایپ‌چکینگ از فاز build یک الگوی استاندارد است. با noEmit: true، TS فقط تایپ‌چکینگ می‌کند و فایلی تولید نمی‌کند. این الگو اجازه می‌دهد که از bundler سریع‌تر (esbuild) برای build استفاده کنید و در همان زمان، تایپ‌چکینگ دقیق TS را در CI/CD اجرا کنید. این جداسازی، تفاوت بین یک build سریع و یک build کند است.
  5. Interaction با Editor و Language Server: تنظیمات tsconfig مستقیماً روی رفتار editor و autocomplete اثر می‌گذارد. VS Code از tsconfig برای فهم ساختار پروژه، مسیر Aliasها، و انواع تایپ‌ها استفاده می‌کند. اگر تنظیمات درست باشد، autocomplete و go-to-definition کامل کار می‌کند. اگر تنظیمات ناقص باشد، این ویژگی‌ها نیمه‌کاره می‌شوند و بهره‌وری توسعه‌دهنده کاهش پیدا می‌کند. مطالعه‌ی موازی در آموزش تایپ اسکریپت از صفر و مفاهیم پیشرفته جاوااسکریپت.

یک تجربه‌ی واقعی از پروژه‌ای که با Project References روبرو شدیم: در یک monorepo که شامل frontend، backend و shared types بود، هر بار که یک تایپ مشترک تغییر می‌کرد، TS مجبور بود تمام پروژه را دوباره کامپایل کند. با تنظیم references و استفاده از tsc --build، این زمان از ۹۰ ثانیه به ۸ ثانیه کاهش پیدا کرد. تفاوت بین یک چرخه‌ی توسعه‌ی سریع و یک چرخه‌ی کند، همین‌جا ساخته می‌شود.

اگر روی پروژه‌های وردپرسی هستید و می‌خواهید این لایه‌ها را در development pipeline خود اعمال کنید، پیشنهاد می‌کنم ابتدا به توسعه وردپرس از صفر نگاهی بیندازید. برای مطالعه‌ی موازی با استانداردها و معماری، استانداردهای HTML و CSS و CSS مدرن از Flexbox تا Grid دید وسیع‌تری می‌دهند. برای درک این لایه در چارچوب کارایی، بهینه سازی جاوااسکریپت و بهینه‌سازی سرعت سایت منابع کلیدی هستند. اگر روی موضوع کیفیت کد و تست متمرکز هستید، ابزارهای CI/CD و گیت در وردپرس را هم ببینید.

tsconfig.json در TypeScript مثل پنل تنظیمات یک هواپیماست: اگر تنظیمات پیش‌فرض را بپذیرید، پرواز می‌کنید اما در ارتفاع پایین. اگر تنظیمات را آگاهانه بچینید، سقف پروازتان بسیار بالاتر می‌رود.

ایستگاه پایانی این مسیر

تنظیمات tsconfig در TypeScript را می‌توان در یک جمله خلاصه کرد: «فایلی که تصمیم می‌گیرد TS چطور فکر کند و کد شما چطور کامپایل شود.» سه درس که از این مسیر با خودم بردم:

  1. strict را از روز اول فعال کنید. این یک تصمیم غیرقابل‌مذاکره در پروژه‌های جدید است. در پروژه‌های موجود، مهاجرت تدریجی به strict را در برنامه‌ی بلندمدت قرار دهید. هزینه‌ی امروز این تصمیم، پاداش بزرگتری در آینده دارد.
  2. paths و baseUrl را جدی بگیرید. importهای طولانی و پر از مسیرهای نسبی، خوانایی و نگهداری کد را به‌طور محسوسی پایین می‌آورند. سه یا چهار Alias اصلی، تفاوت بین یک پروژه‌ی تمیز و یک پروژه‌ی به‌هم‌ریخته را می‌سازد.
  3. تنظیمات را بر اساس سناریو انتخاب کنید. تنظیمات React با Node.js و کتابخانه‌ی عمومی متفاوت است. هیچ تنظیم یگانه‌ای برای همه‌ی سناریوها وجود ندارد. یک tsconfig مبتنی بر اصول، تفاوت بین یک پروژه‌ی معمولی و یک پروژه‌ی حرفه‌ای را می‌سازد.

مسیر یادگیری فرانت‌اند با این نوشته تمام نمی‌شود. اگر می‌خواهید مرحله‌ی بعدی را بردارید، آموزش تایپ اسکریپت از صفر، ماژول ها در تایپ اسکریپت و کلاس در تایپ اسکریپت سه قدم منطقی بعدی هستند. اگر روی فریم‌ورک‌ها متمرکز هستید، تایپ اسکریپت با React، تایپ اسکریپت با Node.js و ابزارهای CI/CD دید وسیع‌تری می‌دهند. اگر هم به سمت خطاها و دیباگ می‌روید، خطاهای رایج تایپ اسکریپت و گیت در وردپرس منابع کلیدی هستند.

از تجربه‌ی خودم، tsconfig همیشه آن فایلی است که در ابتدای پروژه نوشته می‌شود و بعد شش ماه دست‌نخورده می‌ماند تا روزی که یک باگ عجیب یا کندی محسوس، همه را مجبور به بازکردنش می‌کند. اگر در پروژه‌ای تنظیمات خاصی را برای یک سناریوی غیرمنتظره اعمال کرده‌اید — یا برعکس، با تنظیم نادرست tsconfig ساعت‌ها وقت تلف کرده‌اید — آن تجربه را با ما در میان بگذارید. آن نوع روایت‌ها، برای کسی که امروز در حال راه‌اندازی یک پروژه‌ی جدید است، ارزش عملی بیشتری از هر مستند رسمی دارند.