فضای نام (Namespaces)
«فضای نام تایپ اسکریپت» ظرف نام گذاری است. یعنی کدهای مرتبط را گروه می کند. سپس از تداخل نام جلوگیری می کند. مثل قفسه های برچسب خورده در کتابخانه مدرسه.
درک سریع فضای نام
«فضای نام (Namespace)» یک بلوک نام دار است. بنابراین اعضا با نقطه فراخوانی می شوند. همچنین می توانیم با export، دسترسی بیرونی بدهیم.
سینتکس پایه فضای نام
تعریف و استفاده از فضای نام
کد زیر گروه «Validation» می سازد. سپس کلاس ها را صادر می کند. در پایان از آن ها استفاده می کنیم.
namespace Validation {
export interface StringValidator {
isValid(s: string): boolean;
}
const lettersRegexp = /^[A-Za-z]+$/;
export class LettersValidator implements StringValidator {
isValid(s: string): boolean {
return lettersRegexp.test(s);
}
}
export class ZipCodeValidator implements StringValidator {
isValid(s: string): boolean {
return /^[0-9]+$/.test(s) && s.length === 5;
}
}
}
let letterValidator = new Validation.LettersValidator();
let zipCodeValidator = new Validation.ZipCodeValidator();
console.log(letterValidator.isValid('Hello'));
console.log(letterValidator.isValid('Hello123'));
console.log(zipCodeValidator.isValid('12345'));
console.log(zipCodeValidator.isValid('1234'));
ویژگی های پیشرفته فضاهای نام
فضاهای نام تو در تو
می توان فضاها را تو در تو ساخت. بنابراین ساختار پروژه منظم تر می شود.
namespace App {
export namespace Utils {
export function log(msg: string): void {
console.log(`[LOG]: ${msg}`);
}
export function error(msg: string): void {
console.error(`[ERROR]: ${msg}`);
}
}
export namespace Models {
export interface User {
id: number;
name: string;
email: string;
}
export class UserService {
getUser(id: number): User {
return { id: id, name: 'John Doe', email: 'john@example.com' };
}
}
}
}
App.Utils.log('Application starting');
const userService = new App.Models.UserService();
const user = userService.getUser(1);
App.Utils.log(`User loaded: ${user.name}`);
نام مستعار برای فضا یا اعضا
نام های طولانی را با alias کوتاه کن. بنابراین کد خواناتر می شود.
namespace VeryLongNamespace {
export namespace DeeplyNested {
export namespace Components {
export class Button {
display(): void {
console.log('Button displayed');
}
}
export class TextField {
display(): void {
console.log('TextField displayed');
}
}
}
}
}
const button1 = new VeryLongNamespace.DeeplyNested.Components.Button();
button1.display();
import Components = VeryLongNamespace.DeeplyNested.Components;
const button2 = new Components.Button();
button2.display();
import Button = VeryLongNamespace.DeeplyNested.Components.Button;
const button3 = new Button();
button3.display();
فضای نام در چند فایل
تقسیم یک فضا بین فایل ها
با کامنت reference فایل ها مرتبط می شوند. سپس فضای نام یکی می شود.
namespace Validation {
export interface StringValidator {
isValid(s: string): boolean;
}
}
/// <reference path="validators.ts" />
namespace Validation {
const lettersRegexp = /^[A-Za-z]+$/;
export class LettersValidator implements StringValidator {
isValid(s: string): boolean {
return lettersRegexp.test(s);
}
}
}
/// <reference path="validators.ts" />
namespace Validation {
const zipCodeRegexp = /^[0-9]+$/;
export class ZipCodeValidator implements StringValidator {
isValid(s: string): boolean {
return zipCodeRegexp.test(s) && s.length === 5;
}
}
}
/// <reference path="validators.ts" />
/// <reference path="letters-validator.ts" />
/// <reference path="zipcode-validator.ts" />
let validators: { [s: string]: Validation.StringValidator } = {};
validators['letters'] = new Validation.LettersValidator();
validators['zipcode'] = new Validation.ZipCodeValidator();
let strings = ['Hello', '98052', '101'];
strings.forEach((s) => {
for (let name in validators) {
const ok = validators[name].isValid(s);
console.log(`"${s}" - ${ok ? 'matches' : 'does not match'} ${name}`);
}
});
tsc --outFile sample.js main.ts
فضای نام یا ماژول؟
در پروژه های جدید از ماژول ها استفاده کن. اما برای کدهای قدیمی، فضای نام مفید است.
الگوهای پیشرفته فضای نام
افزودن اعلان ها با «Declaration Merging» امکان پذیر است. مثال زیر Express را گسترش می دهد.
declare namespace Express {
interface Request {
user?: { id: number; name: string };
}
interface Response {
json(data: any): void;
}
}
declare namespace Express {
interface Request {
requestTime?: number;
log(message: string): void;
}
interface UserSession {
userId: number;
expires: Date;
}
}
فضای نام با جنریک ها
می توان مخزن داده عمومی ساخت. سپس پیاده سازی در حافظه نوشت.
namespace DataStorage {
export interface Repository<T> {
getAll(): T[];
getById(id: number): T | undefined;
add(item: T): void;
update(id: number, item: T): boolean;
delete(id: number): boolean;
}
export class InMemoryRepository<T> implements Repository<T> {
private items: T[] = [];
getAll(): T[] {
return [...this.items];
}
getById(id: number): T | undefined {
return this.items[id];
}
add(item: T): void {
this.items.push(item);
}
update(id: number, item: T): boolean {
if (id >= 0 && id < this.items.length) {
this.items[id] = item;
return true;
}
return false;
}
delete(id: number): boolean {
if (id >= 0 && id < this.items.length) {
this.items.splice(id, 1);
return true;
}
return false;
}
}
}
interface User {
id: number;
name: string;
email: string;
}
const userRepo = new DataStorage.InMemoryRepository<User>();
userRepo.add({ id: 1, name: 'John Doe', email: 'john@example.com' });
const allUsers = userRepo.getAll();
مهاجرت از فضای نام به ماژول
برای پروژه مدرن، فایل ها را ماژول کن. سپس import و export استفاده کن.
namespace MyApp {
export namespace Services {
export class UserService {
getUser(id: number) {
/* ... */
}
}
}
}
export class UserService {
getUser(id: number) {
/* ... */
}
}
import { UserService as Svc } from './services/UserService';
const userService2 = new Svc();
گام های عملی
- یک فضای نام بساز و اعضا را export کن.
- برای نام های طولانی، alias تعریف کن.
- اگر چند فایل داری، reference بده.
- در پروژه جدید، به ماژول مهاجرت کن.
- از «فضای نام تایپ اسکریپت» فقط در سناریوهای لازم استفاده کن.
جمع بندی سریع
- فضای نام، گروه بندی منطقی می دهد.
- از تداخل نام جلوگیری می کند.
- برای کد قدیمی مفید است.
- برای کد جدید، ماژول بهتر است.
برای ادامه مطالعه، به انواع لیترال و امضاهای اندیس سر بزن. همچنین برای سئو، این لینک را ببین: فضای نام تایپ اسکریپت.