اجتناب از درگیری نامگذاری میتواند ناخوشایند باشد و منجر به کدهای سختگیرانه شود، اما فضاهای نام راهحل مناسبی را ارائه میدهند.
تصادم نامگذاری زمانی رخ می دهد که دو یا چند جزء کد از یک نام برای یک متغیر، تابع یا کلاس استفاده می کنند. آنها در پروژه های بزرگ که در آن افراد زیادی بر روی یک پایگاه کد کار می کنند رایج هستند. آنها می توانند تعیین اینکه کدام مؤلفه کد مسئول اشکالات است را دشوار می کنند.
با استفاده از فضاهای نام، می توانید کد خود را سازماندهی و مدیریت کنید تا گروه هایی از اجزای مرتبط تحت یک شناسه مشترک قرار گیرند. این خطر تضاد نامگذاری را کاهش میدهد.
ایجاد فضای نام
می توانید با استفاده از کلمه کلیدی namespace در TypeScript فضای نام ایجاد کنید. آن را با یک شناسه دنبال کنید تا فضای نام و یک بلوک محصور شده توسط پرانتزها نامگذاری شود. سینتکس مشابهی است که برای ایجاد کلاس در جاوا اسکریپت استفاده می کنید.
مثلا:
namespace Example {}
سپس میتوانید اعضای فضای نام – متغیرها، توابع و کلاسها – را در بلوک فضای نام اعلام کنید:
namespace Example {
export function Foo(): void {
console.log("This is a function inside the Example namespace");
}
export class Bar {
property: string;
constructor(property: string) {
this.property = property;
}
}
export const baz = "This is a namespace variable"
}
در مثال بالا، Foo، Bar و baz اعضای فضای نام Example هستند. به طور پیش فرض، شما فقط می توانید به اعضای یک فضای نام در همان فضای نام دسترسی داشته باشید. از کلمه کلیدی صادرات استفاده کنید تا هر یک از اعضای فضای نام در خارج از آن قابل دسترسی باشد.
شما می توانید با فراخوانی نام عضو فضای نام با استفاده از علامت نقطه به همه اعضای در دسترس عمومی یک فضای نام دسترسی داشته باشید:
Example.foo(); // This is a function inside the Example namespace
const bar = new Example.Bar("string");
console.log(bar.property); // string
console.log(Example.baz); // This is a namespace variable
فضای نام تودرتو
TypeScript به شما اجازه می دهد تا فضاهای نام را در فضای نام دیگر قرار دهید تا یک ساختار سلسله مراتبی برای کد خود ایجاد کنید. فضاهای نام تودرتو با گروه بندی فضاهای نام مرتبط تحت یک شناسه مشترک می توانند خطرات برخورد نامگذاری را کاهش دهند.
مثلا:
namespace Example {
export const property_1 = "Foo";
export namespace Bar {
export const printFoo = function () {
console.log(property_1);
};
}
export namespace Baz {
export class Foo {
property: string;
constructor(property: string) {
this.property = property;
}
}
}
}
بلوک کد بالا نمونه ای از فضای نام تودرتو را ارائه می دهد. فضای نام Example فضای نام سطح بالایی است که شامل فضای نام Bar و فضای نام Baz است.
میتوانید با استفاده از نماد نقطهای که از ساختار سلسله مراتبی ایجاد شده پیروی میکند، به ویژگیها در یک فضای نام تودرتو دسترسی داشته باشید.
مثلا:
console.log(Example.property_1); // Foo
Example.Bar.printFoo() // Foo
const foo = new Example.Baz.Foo("example")
این کد مثال به هر یک از اعضای فضای نام از طریق فضای نام والد دسترسی پیدا می کند. دسترسی مستقیم به یک ویژگی، به جای اینکه از طریق فضای نام والد آن انجام شود، یک خطا ایجاد می کند:
Example.printFoo()
// error TS2339: Property 'printFoo' does not exist on type 'typeof Example'
اگرچه فضاهای نام تودرتو می توانند به شما در سازماندهی کدتان کمک کنند، اما فضاهای نام عمیق تو در تو ممکن است اثر معکوس ایجاد کنند. فضای نام عمیق تو در تو، خواندن و نگهداری کد شما را سخت تر می کند.
نام مستعار فضای نام
نام مستعار فضای نام یک نام کوتاه شده است که به یک عضو فضای نام داده می شود، که ارجاع آن را آسان تر می کند.
می توانید با استفاده از کلمه کلیدی import و به دنبال آن نامی که می خواهید به نام مستعار اختصاص دهید، یک نام مستعار فضای نام ایجاد کنید. سپس، کلمه کلیدی import و نام مستعار را به یک عضو فضای نام اختصاص دهید.
مثلا:
namespace Car {
export namespace Tesla {
export class ModelX {
create(): String {
return `Model X Created`
}
}
}
export namespace Toyota {
export class Camry {}
}
export namespace Ford {
export class Mustang {}
}
}
// Creating the alias
import tesla = Car.Tesla
const modelX = new tesla.ModelX()
modelX.create() // Model X Created
این مثال یک نام مستعار برای فضای نام Car.Tesla ایجاد می کند. میتوانید از این نام مستعار برای دسترسی آسانتر به ویژگیهای فضای نام تسلا، مانند کلاس ModelX استفاده کنید.
استفاده از فضاهای نام در چندین فایل
برای استفاده از فضای نام در یک فایل دیگر، باید آن را وارد کنید. وارد کردن فضای نام با وارد کردن متغیرها، توابع، کلاسها و غیره متفاوت است. بسته به سیستم ماژول پروژهتان، میتوانید آنها را با استفاده از نیاز یا کلمه کلیدی import وارد کنید.
با این حال، شما فقط می توانید فضاهای نام را با استفاده از دستورالعمل سه اسلش وارد کنید، که یک نظر تک خطی حاوی یک تگ XML است.
مثلا:
// main.ts
/// <reference path="index.ts" />
Example.foo()
این مثال از دستورالعمل سه گانه اسلش در داخل فایل main.ts استفاده می کند. این دستورالعمل به فایل index.ts اشاره می کند که حاوی فضای نام Example است. بدون وارد کردن، فضای نام فقط در همان فایلی که آن را تعریف می کند در دسترس است.
پس از ارجاع به فایل index.ts، می توانید به فضای نام Example و اعضای در دسترس عمومی آن دسترسی داشته باشید. به عنوان مثال، می توانید متد foo را در فضای نام Example فراخوانی کنید.
هنگامی که از چندین فایل استفاده می کنید، باید مطمئن شوید که TypeScript تمام کدهای لازم را کامپایل و بارگذاری می کند. می توانید این کار را با الحاق خروجی از کامپایلر TypeScript با استفاده از گزینه outFile انجام دهید. سپس تمام فایل های ورودی را در یک فایل خروجی جاوا اسکریپت کامپایل می کند. سینتکس کلی برای اجرای کامپایلر به این صورت است:
tsc --outFile <JAVASCRIPT_FILE> <TYPESCRIPT_FILE>
نام فایل جاوا اسکریپت مورد نظر خود را جایگزین
مثلا:
tsc --outFile index.js main.ts
این دستور محتویات فایل main.ts را به همراه تمام فایلهای ارجاع شده توسط دستورالعمل سه اسلش در فایل index.js کامپایل میکند.
همچنین، می توانید هر فایل را به صورت جداگانه مشخص کنید:
tsc --outFile <JAVASCRIPT_FILE> <TYPESCRIPT_FILE_1> <TYPESCRIPT_FILE_2>
توجه به این نکته مهم است که دستور سه گانه فقط زمانی معتبر است که در بالای فایل اعلام شود. اگر بخواهید از آن در جای دیگری استفاده کنید، TypeScript آن را به عنوان یک نظر تک خطی معمولی و بدون معنای خاصی در نظر می گیرد.
آیا باید از فضای نام یا ماژول استفاده کنید؟
در حالی که فضاهای نام منسوخ نشده اند، سازماندهی و مدیریت کد خود با استفاده از ماژول های ES6 اغلب توصیه می شود. نگهداری و مدیریت ماژولها آسانتر است و میتوانید آنها را در چندین فایل گسترده کنید.
علاوه بر این، می توانید روابط بین ماژول ها را از نظر واردات و صادرات در سطح فایل مشخص کنید. فضاهای نام نمی توانند وابستگی های خود را تعریف کنند.
در نهایت، انتخاب بین فضاهای نام و ماژول ها به نیازها و نیازهای خاص پروژه شما بستگی دارد، زیرا هر دو روش ارزشمندی برای سازماندهی و مدیریت کد در TypeScript ارائه می دهند.