در پروژه های JS (in JS Projects)
می خواهی تایپ چکینگ داشته باشی اما فایل ها JS هستند؟ با JSDoc تایپ اسکریپت این امکان فراهم است. «تایپ چکینگ (Type Checking)» یعنی خطای نوع ها زود کشف شوند. بنابراین پروژه جاوااسکریپت امن تر می شود.
شروع سریع با JSDoc تایپ اسکریپت
برای فعال سازی نوع ها در JS این گام ها را برو:
- یک
tsconfig.jsonبساز. checkJsرا روشن کن یا بالای فایل بنویس// @ts-check.
// @ts-check\n\n/**\n * Adds two numbers.\n * @param {number} a\n * @param {number} b\n * @returns {number}\n */\nfunction add(a, b) {\n return a + b;\n}\n
نکته: برچسب // @ts-check تنها برای همان فایل است. بنابراین دقیق تر کنترل می کنی.
اشیاء و رابط ها با JSDoc
نوع دهی شیء درجا
// @ts-check\n\n/**\n * @param {{ firstName: string, lastName: string, age?: number }} person\n */\nfunction greet(person) {\n return `Hello, ${person.firstName} ${person.lastName}`;\n}\n\ngreet({ firstName: 'John', lastName: 'Doe' });\n
تعریف نوع پیچیده با @typedef
// @ts-check\n\n/**\n * @typedef {Object} User\n * @property {number} id\n * @property {string} username\n * @property {string} [email]\n * @property {('admin'|'user'|'guest')} role\n * @property {() => string} getFullName\n */\n\n/** @type {User} */\nconst currentUser = {\n id: 1,\n username: 'johndoe',\n role: 'admin',\n getFullName() {\n return 'John Doe';\n }\n};\n\nconsole.log(currentUser.role);\n
گسترش نوع ها
// @ts-check\n\n/** @typedef {{ x: number, y: number }} Point */\n/** @typedef {Point & { z: number }} Point3D */\n\n/** @type {Point3D} */\nconst point3d = { x: 1, y: 2, z: 3 };\n
نوع های تابع و کال بک ها
تعریف تابع با توضیحات
// @ts-check\n\n/**\n * Calculates the area of a rectangle\n * @param {number} width\n * @param {number} height\n * @returns {number}\n */\nfunction calculateArea(width, height) {\n return width * height;\n}\n\nconst area = calculateArea(10, 20);\n
عبارت های تابعی و کال بک
// @ts-check\n\n/**\n * @callback StringProcessor\n * @param {string} input\n * @returns {string}\n */\n\n/**\n * @type {StringProcessor}\n */\nconst toUpperCase = (str) => str.toUpperCase();\n\n/**\n * @param {string[]} strings\n * @param {StringProcessor} processor\n * @returns {string[]}\n */\nfunction processStrings(strings, processor) {\n return strings.map(processor);\n}\n\nconst result = processStrings(['hello', 'world'], toUpperCase);\n
اُورلود تابع با JSDoc
// @ts-check\n\n/**\n * @overload\n * @param {string} a\n * @param {string} b\n * @returns {string}\n */\n/**\n * @overload\n * @param {number} a\n * @param {number} b\n * @returns {number}\n */\n/**\n * @param {string | number} a\n * @param {string | number} b\n * @returns {string | number}\n */\nfunction add(a, b) {\n if (typeof a === 'string' || typeof b === 'string') {\n return String(a) + String(b);\n }\n return a + b;\n}\n\nconst strResult = add('Hello, ', 'World!');\nconst numResult = add(10, 20);\n
نوع های پیشرفته در JSDoc
یونین و اینترسکشن
// @ts-check\n\n/** @typedef {{ name: string, age: number }} Person */\n/** @typedef {Person & { employeeId: string }} Employee */\n/** @typedef {Person | { guestId: string, visitDate: Date }} Visitor */\n\n/** @type {Employee} */\nconst employee = {\n name: 'Alice',\n age: 30,\n employeeId: 'E123'\n};\n\n/** @type {Visitor} */\nconst guest = {\n guestId: 'G456',\n visitDate: new Date()\n};\n\n/**\n * @param {Visitor} visitor\n * @returns {string}\n */\nfunction getVisitorId(visitor) {\n if ('guestId' in visitor) {\n return visitor.guestId;\n }\n return visitor.name;\n}\n
Mapped و Conditional به زبان ساده
// @ts-check\n\n/**\n * @template T\n * @typedef {[K in keyof T]: T[K] extends Function ? K : never}[keyof T] MethodNames\n */\n\n/**\n * @template T\n * @typedef {{\n * [K in keyof T as `get${'<'}Capitalize<string & K>{'>'}`]: () => T[K]\n * }} Getters\n */\n\n/** @type {Getters<{ name: string, age: number }>} */\nconst userGetters = {\n getName: () => 'John',\n getAge: () => 30\n};\n\nconst name = userGetters.getName();\nconst age = userGetters.getAge();\n
وارد کردن نوع ها از فایل های دیگر
// @ts-check\n\n/** @typedef {import('./types').User} User */\n/** @typedef {import('express').Request} ExpressRequest */\n/** @typedef {import('./api').default as ApiClient} ApiClient */\n
ساخت فایل اعلان نوع (.d.ts)
گاهی کتابخانه بدون تایپ داری. پس یک فایل اعلان بساز. سپس در JS استفاده کن.
// types.d.ts\ndeclare module 'my-module' {\n export interface Config {\n apiKey: string;\n timeout?: number;\n retries?: number;\n }\n\n export function initialize(config: Config): void;\n export function fetchData<T = any>(url: string): Promise<T>;\n}\n
// @ts-check\n\n/** @type {import('my-module').Config} */\nconst config = {\n apiKey: '12345',\n timeout: 5000\n};\n\nimport { initialize } from 'my-module';\ninitialize(config);\n
بهترین تجربه و خطاهای رایج
نکته: برای نوع های تکراری از @typedef استفاده کن. برای جنریک ها @template بنویس. در فایل های مهم // @ts-check را فعال کن.
هشدار: نبودن // @ts-check نوع ها را خاموش می کند. اشتباه نوشتن JSDoc چک را می شکند. فایل های سنگین می توانند کند شوند.
ادامه مسیر
برای مهاجرت کامل به تایپ اسکریپت به مهاجرت به تایپ اسکریپت برو. همچنین بخش JSDoc تایپ اسکریپت را به عنوان مرجع سریع نگه دار. سپس برای الگوهای فراگیر به دکوراتورها سر بزن.
جمع بندی سریع
// @ts-checkرا زود فعال کن.- برای نوع های مشترک،
@typedefبساز. - کال بک ها را با
@callbackتعریف کن. - نوع وارداتی را با
import()بیار. - برای کتابخانه ها، فایل
.d.tsبساز.