نظرات مطالب
شروع کار با webpack - قسمت دوم
در بخش استفاده از لودر‌ها > استفاده از لودر تایپ اسکریپت
در فایل پیکربندی webpack بعد از اعمال لودر TypeScript میبایست main.js به main.ts آپدیت شود تا لودر تایپ اسکریپت بتواند به درستی عملیات transpile را انجام دهد. 
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت اول - نصب پیشنیازها
ممنون از مطالبتون.
من با VS 2013  کار می‌کنم، در قسمت "افزودن فایل tsconfig.json به پروژه" در لیست ظاهر شده، گزینه‌ی TypeScript JSON Configuration File برای من نمایش داده نمی‌شود مشکل کجاست؟
نظرات مطالب
مبانی TypeScript؛ تنظیمات TypeScript در ویژوال استودیو
جهت تکمیل این بحث
برای VS 2013 این اصلاح را هم که مرتبط با AngularJS 2.0 هست، نصب کنید (پس از نصب پلاگین آن). این اصلاحیه‌ی ویژه برای VS 2015 درصورتیکه TypeScript 2.0.3 را نصب کرده باشید، نیازی نیست.
نظرات مطالب
شروع به کار با AngularJS 2.0 و TypeScript - قسمت اول - نصب پیشنیازها
نیاز به یک Gulp Task دارد تا تمام فایل‌های پروژه به همراه فایل‌های AngularJS 2.0 یکی شوند؛ به همراه uglify و minify خودکار: «شروع به کار با AngularJS 2.0 و TypeScript - قسمت دوازدهم - توزیع برنامه»
 
نظرات مطالب
مبانی TypeScript؛ تنظیمات TypeScript در ویژوال استودیو
Review Pane از نسخه 2015 Web Essentials به دلیل تداخل با کامپایلر TypeScript، حذف شده است
راه حل جایگزین فعلی گشودن هر دو فایل به صورت پنجره‌های کنار هم از طریق منوی Window میباشد.

مطالب
(Domain Driven Design) به زبان ساده
DDD چیست؟ روشی است ساده، زیبا، در وهله اول برای تفکر، و در وهله دوم برای توسعه نرم افزار، که می‌توان بر مبنای آن نیازمندیهای پویا و پیچیده‌ی حوزه دامین را تحلیل، مدل و نهایتا پیاده سازی کرد.
در این روش توسعه نرم افزار تاکید ویژه ای بر الزامات زیر وجود دارد:
  • تمرکز اصلی پروژه، باید صرف فائق آمدن بر مشکلات و پیچیدگیهای موجود در دامین شود.
  • پیچیدگیهای موجود در دامین پس از شناسایی به یک مدل تبدیل شوند.
  • برقراری یک رابطه‌ی خلاق بین متخصصان دامین و افراد تیم توسعه برای بهبود مستمر مدل ارائه شده که نهایتا راه حل مشکلات دامین است بسیار مهم می‌باشد.
مبدع این روش کیست؟
بخوانید:
Eric Evans is a specialist in domain modeling and design in large business systems. Since the early 1990s, he has worked on many projects developing large business systems with objects and has been deeply involved in applying Agile processes on real projects. Eric is the author of "Domain-Driven Design" (Addison-Wesley, 2003) and he leads the consulting group Domain Language, Inc. 
ویدیویی سخنرانی اریک اوانس با عنوان: DDD: putting the model to work
شرایط موفقیت اجرای یک پروژه مبتنی بر DDD چیست؟
  • دامین ساده و سر راست نباشد.
  • افراد تیم توسعه با طراحی / برنامه نویسی شی گرا آشنا باشند.
  • دسترسی به افراد متخصص در مسائل مرتبط با دامین آسان باشد.
  • فرآیند تولید نرم افزار، یک فرآیند چابک باشد.
در این باره چه چیزی بخوانم؟
برای شروع توصیه می‌کنم بخوانید: Domain-Driven Design: Tackling Complexity in the Heart of Software 
نویسنده: Eric Evans


در ادامه می‌پردازم به اینکه ابزار DDD برای شکستن پیچیدگیهای دامین و تبدیل آنها به مدل کدامند؟
پاسخ خلاصه در زیر آمده است. دعوت می‌کنم تا شرح هر یک از این موارد را در پستهای بعدی پیگیر باشید.
  • Entity
  • Value Object
  • Aggregate
  • Service
  • Repository
  • Factory

 قبلا توضیح داده بودم که طراحی متاثر از حوزه‌ی کاری (Domain Driven Design) منجر به کاهش، درک و نهایتا قابل مدیریت کردن پیچیدگیهای موجود در حوزه عملیاتی نرم افزار (Domain) می‌شود. توجه کنیم که تحلیل و مدلسازی، فعالیتهای رایج در حوزه هایی مانند حمل و نقل، اکتشافات، هوا فضا، شبکه‌های اجتماعی و ... می‌تواند بسیار دشوار باشد.

برای مثال فرض کنید که می‌خواهید به مدلسازی نرم افزاری بپردازید که هدف تولید آن پیش بینی وضع آب و هوا است. این حوزه کاری (پیش بینی وضع آب و هوا) بویژه همواره یکی از حوزه (Domain)‌های  پیچیده برای طراحان مدل محسوب می‌شود. DDD روشی است که با بکار گیری آن می‌توانید این پیچیدگیها را بسیار کاهش دهید. توسعه سیستمهای پیچیده بدون رعایت قواعدی همه فهم، نهایتا نرم افزار را به مجموعه ای از کدهای غیر خوانا و دیرفهم تبدیل می‌کند که احتمالا نسل بعدی توسعه دهندگانش را تشویق به بازنویسی آن خواهد کرد.

DDD در واقع روشی است برای دقیق‌تر فکر کردن در مورد نحوه ارتباط و تعامل اجزای مدل با یکدیگر. این سبک طراحی (DDD) به تولید مدلی از اشیاء می‌انجامد که نهایتا تصویری قابل درک (Model) از مسائل مطرح در حوزه‌ی کاری ارائه می‌دهند. این مدل ارزشمند است وقتی که:

1- نمایی آشکار و در عین حال در نهایت سادگی و وضوح از همه‌ی مفاهیمی باشد که در حوزه عملیاتی نرم افزار(Domain) وجود دارد.
2- به تناسب درک کاملتری که از حوزه کاری کسب می‌شود بتوان این مدل را بهبود و توسعه داد(Refactoring).

در DDD کوشش می‌شود که با برقراری ارتباطی منطقی بین اشیاء، و رعایت سطوحی از انتزاع یک مشکل بزرگتر را به مشکلات کوچکتر شکست و سپس به حل این مشکلات کوچکتر پرداخت.

توجه کنیم که DDD به چگونگی سازماندهی اشیاء توجه ویژه ای دارد ولی DDD چیزی درباره برنامه نویسی شی گرا نیست. DDD متدولوژیی است که با بهره گیری از مفاهیم شی گرایی و مجموعه ای از تجارب ممتاز توسعه نرم افزار (Best Practice) پیچیدگیها را و قابلیت توسعه و نگهداری نرم افزار را بهبود می‌دهد.

ایده مستتر در DDD ساده است. اگر در حوزه کاری مفهوم (Concept) ارزشمندی وجود دارد باید بتوان آن را به وضوح در مدل مشاهده کرد. برای مثال صحیح نیست که یک شرط ارزشمند حوزه کسب و کار را با مجموعه‌ی سخت فهمی از If / Else ها، در مدل نشان داد. این شرط مهم را می‌توان با Specification pattern پیاده سازی کرد تا تصویری خوانا‌تر از Domain در مدل بوجود بیاید.

مدلی که دستیبابی به آن در DDD دنبال می‌شود مدلی است سر راست و گویا با در نظر گرفتن همه جوانب و قواعد حوزه‌ی عمل نرم افزار. در این مدل مطلوب و ایده آل به مسائل ذخیره سازی (persistence) پرداخته نمی‌شود. (رعایت اصل PI). این مدل نگران چگونگی نمایش داده‌ها در واسط کاربری نیست. این مدل نگران داستانهای Ajax نیست. این مدل یک مدل Pureاست که دوست داریم حتی المقدور POCO باشد. این مدلی است برای بیان قواعد و منطق موجود در حوزه عمل نرم افزار. این قواعد همیشه تغییر می‌کنند و مدلی که از آموزه‌های DDDالهام گرفته باشد، راحت‌تر پذیرای این تغییرات خواهد بود. به همین دلیل DDD با روشهای توسعه به سبک اجایل نیز قرابت بیشتری دارد.  
مطالب
نوع‌های نال نپذیر در TypeScript
تا پیش از ارائه‌ی کامپایلر TypeScript 2.0، مقادیر null و undefined، به هر نوعی قابل انتساب بودند و امکان تفکیک آن‌ها وجود نداشت که این مورد می‌تواند منشاء بروز بسیاری از خطاهای در زمان اجرا شود.
let name: string;
name = "Vahid"; // OK
name = null; // OK
name = undefined;  // OK
let age: number;
age = 24; // OK
age = null; // OK
age = undefined;  // OK
برای نمونه در اینجا یک متغیر رشته‌ای و همچنین عددی تعریف شده‌اند که انتساب null و یا undefined نیز به آن‌ها مجاز است. این مورد جهت نوع‌های ورودی و خروجی متدها، اشیاء و آرایه‌ها نیز میسر است.


نوع null در TypeScript

همانند JavaScript، نوع null تنها یک مقدار معتبر نال را می‌تواند داشته باشد و نمی‌توان برای مثال یک رشته را به آن انتساب داد. اما انتساب این مقدار به هر نوع متغیر دیگری، سبب پاک شدن مقدار آن خواهد شد. با فعالسازی strictNullChecks، این نوع را تنها به نوع‌های نال‌پذیر می‌توان انتساب داد.


نوع undefined در TypeScript

هر متغیری که مقداری به آن انتساب داده نشده باشد، با undefined مقدار دهی می‌شود. این مورد حتی جهت خروجی متدها نیز صادق است و اگر return ایی در آن‌ها فراموش شود، این خروجی نیز به undefined تفسیر می‌شود.
در اینجا نیز اگر نوع متغیری به undefined تنظیم شد، این متغیر تنها مقدار undefined را می‌تواند بپذیرد. تنها با خاموش کردن پرچم strictNullChecks می‌توان آن‌را به اعداد، رشته‌ها و غیره نیز انتساب داد.


فعالسازی نوع‌های نال نپذیر در TypeScript

برای فعالسازی این قابلیت، نیاز است پرچم strictNullChecks را در فایل تنظیمات کامپایلر به true تنظیم کرد:
{
    "compilerOptions": {
        "strictNullChecks": true
    }
}
از این پس دیگر نمی‌توان null و undefined را به هر نوعی انتساب داد و این‌ها تنها به خودشان و یا نوع any، قابل انتساب هستند. برای مثال اکنون نوع number فقط یک عدد است و دیگر قابلیت پذیرش null و یا undefined را ندارد. البته در اینجا یک استثناء هم وجود دارد: undefined را می‌توان به نوع void نیز انتساب داد.
برای مثال اگر متدی، رشته‌ای را به عنوان پارامتر قبول کند، تا پیش از TypeScript 2.0 و فعالسازی strictNullChecks آن، مشخص نبود که رشته‌ی دریافتی از آن واقعا یک رشته‌است و یا شاید null. اما اکنون یک رشته، فقط یک رشته‌است و دیگر نال پذیر نیست.
 let foo: string = null; // Error! Type 'null' is not assignable to type 'string'.
به این ترتیب دیگر به خطاهای زمان اجرایی مانند خطاهای ذیل نخواهیم رسید:
Uncaught ReferenceError: foo is not defined
Uncaught TypeError: window.foo is not a function

این مورد برای آرایه‌ها نیز صادق است:
// With strictNullChecks set to false
let d: Array<number> = [null, undefined, 10, 15]; //OK
let e: Array<string> = ["pie", null, ""];  //OK
 
 
// With strictNullChecks set to true
let d: Array<number> = [null, undefined, 10, 15]; // Error
let e: Array<string> = ["pie", null, ""]; // Error
اگر strictNullChecks فعال شود، دیگر نمی‌توان به اعضای یک آرایه مقادیر null و یا undefined را نسبت داد.


ساده سازی تعریف بررسی‌های با پرچم strict، در TypeScript 2.3

تعداد گزینه‌های قابل تنظیم در فایل tsconfig روز به روز بیشتر می‌شوند. به همین جهت برای ساده سازی فعالسازی آن‌ها، از TypeScript 2.3 به بعد، پرچم strict نیز به این تنظیمات اضافه شده‌است. کار آن فعالسازی یکجای تمام بررسی‌های strict است؛ مانند noImplicitAny، strictNullChecks و غیره.
{ 
    "compilerOptions": { 
        "strict": true  /* Enable all strict type-checking options. */ 
    } 
}
در این حالت اگر نیاز به لغو یکی از گزینه‌ها بود، می‌توان به صورت ذیل عمل کرد:
{ 
    "compilerOptions": { 
        "strict": true, 
        "noImplicitThis": false 
    } 
}
گزینه‌ی strict تمام بررسی‌های متداول را فعال می‌کند؛ اما ذکر و تنظیم صریح noImplicitThis به false، تنها این یک مورد را لغو خواهد کرد.

یک نکته: اجرای دستور tsc --init ، سبب تولید یک فایل tsconfig.json از پیش تنظیم شده، بر اساس آخرین قابلیت‌های کامپایلر TypeScript می‌شود.


اما ... اکنون چگونه یک نوع را نال‌پذیر کنیم؟

TypeScript به همراه دو نوع ویژه‌ی null و undefined نیز شده‌است که تنها دارای مقادیر null و undefined می‌توانند باشند. به این معنا که در حین تعریف نوع یک متغیر، می‌توان این دو را نیز ذکر کرد و دیگر تنها به عنوان دو مقدار مطرح نیستند. به این ترتیب می‌توان از آن‌ها یک union type را ایجاد کرد:
 let foo: string | null = null; // Okay!
اکنون تنها در این حالت است که متغیر foo می‌تواند یک رشته و یا یک null را دریافت کند و یا اگر مثال ابتدای بحث را بخواهیم اصلاح کنیم، به نمونه‌ی ذیل خواهیم رسید:
let name: string | null;
name = "Vahid"; // OK
name = null; // OK
name = undefined;  // Error
یکی دیگر از مزایای این روش، وضوح بیشتر تعریف نوع متغیرها و به نوعی «خود مستند سازی» بهتر آن‌ها است. در این حالت یا به صورت صریح مشخص می‌کنیم که متدی فقط یک رشته را می‌پذیرد و یا با ذکر string | null، به استفاده کننده اعلام می‌کنیم که ارسال null نیز به آن پیش بینی شده‌است و به نتیجه‌ی نامشخصی منتهی نخواهد شد.

یک نکته:
تا پیش از این اگر متغیری را به این صورت تعریف می‌کردیم:
let z = null;
نوع آن any درنظر گرفته می‌شد. اما اکنون، نوع آن تنها null است و تنها مقداری را هم که می‌تواند بپذیرد نال خواهد بود.


بررسی انتساب، پیش از استفاده

با فعالسازی strictNullChecks، اکنون کامپایلر برای تمام نوع‌هایی که undefined نیستند، یک مقدار اولیه را پیش از استفاده‌ی از آن‌ها درخواست می‌کند:
testAssignedBeforeUseChecking() {
    let x: number;
    console.log(x);
}
در اینجا چون x از نوع عددی است، به علت عدم مقدار دهی اولیه، قابلیت استفاده‌ی از آن وجود ندارد و کامپایلر خطای ذیل را اعلام می‌کند:
 [ts] Variable 'x' is used before being assigned.

اما در حالت ذیل، عدد z می‌تواند عدد و یا undefined باشد؛ به همین جهت کامپایلر با استفاده‌ی از آن مشکلی نخواهد داشت:
let z: number | undefined;
console.log(z);

یک نکته: خواص و پارامترهای اختیاری، به صورت خودکار دارای نوع undefined نیز هستند. برای مثال امضای متد ذیل:
method1(x?: number) {
}
با متد زیر یکی است:
method1(x?: number | undefined) {
}


اجبار به بررسی نال نبودن مقادیر، پیش از استفاده‌ی از آن‌ها در متدهای نال نپذیر

اگر پارامتر متدی یا خاصیت شیءایی نال پذیر نباشند، با ارسال مقدار نوعی به آن‌ها که می‌تواند null و یا undefined را بپذیرد، یک خطای زمان کامپایل صادر خواهد شد. در اینجا محافظ‌های نوع‌ها توسعه یافته‌اند تا اگر بررسی نال یا undefined بودن مقداری انجام شد، مشکلی در جهت استفاده‌ی از آن‌ها نباشد:
  f(x: number): string {
    return x.toString();
  }

  testTypeGuards() {
    let x: number | null | undefined;
    if (x) {
      this.f(x);  // Ok, type of x is number here
    } else {
      this.f(x);  // Error, type of x is number? here
    }
  }
در این مثال، متد f فقط یک عدد را می‌پذیرد (و نه نال و یا undefined). اما در حین کاربرد آن در متد testTypeGuards، مقدار متغیر x می‌تواند یک عدد، نال و یا undefined باشد. چون پیش از اولین استفاده‌ی از متد f در اینجا، بررسی دارای مقدار بودن این متغیر صورت گرفته‌است، فراخوانی صورت گرفته، مجاز است. اما در قسمت else این شرط، کامپایلر خطای ذیل را صادر می‌کند:
 Argument of type 'number | null | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.

امکان این بررسی در مورد عبارات شرطی نیز صادق است:
getLength(s: string | null) {
   return s ? s.length : 0;
}


توسعه‌ی محافظ‌های نوع‌ها جهت کار با نوع‌های نال نپذیر

در مثال ذیل، خروجی متد isNumber دارای امضایی به همراه is است:
isNumber(n: any): n is number { // type guard
   return typeof n === "number";
}
به یک چنین متدهایی type guard گفته می‌شود که امکان بررسی یک نوع را میسر می‌کنند. از این امکان می‌توان جهت بررسی بهتر پارامترها و یا خواص اختیاری استفاده کرد:
  usedMb(usedBytes?: number): number | undefined {
    return this.isNumber(usedBytes) ? (usedBytes / (1024 * 1024)) : undefined;
  }
یک چنین بررسی، بهتر است از بررسی ذیل:
  usedMb2(usedBytes?: number): number | undefined {
    return usedBytes ? (usedBytes / (1024 * 1024)) : undefined;
  }
از این جهت که عبارت شرطی بررسی شده، مقدار صفر را نیز به صورت undefined بازگشت خواهد داد (if(0) به false تعبیر می‌شود و قسمت else این شرط فراخوانی خواهد شد).
همچنین امضای متد نیز به number | undefined تغییر یافته‌است. در غیر اینصورت، خطای زمان کامپایل Type undefined is not assignable to type number صادر خواهد شد.
در حین استفاده‌ی از یک چنین متدی، دیگر نمی‌توان به خروجی آن به صورت ذیل دسترسی یافت:
  formatUsedMb(): string {
    //ERROR: TS2531: Object is possibly undefined
    return this.usedMb(123).toFixed(0).toString();
  }
چون مقدار usedMb می‌تواند undefined باشد، باید ابتدا آن‌را بررسی کرد:
  formatUsed(): string {
    const usedMb = this.usedMb(123);
    return usedMb ? usedMb.toFixed(0).toString() : "";
  }


لغو بررسی strictNullChecks به صورت موقت

با استفاده از اپراتور ! می‌توان به کامپایلر اطمینان داد که این متغیر یا خاصیت، دارای مقدار نال نیست و نخواهد بود:
export interface User {
  name: string;
  age?: number;
}
در این اینترفیس، خاصیت age به صورت اختیاری تعریف شده‌است. برای نمایش مقدار age با فعال بودن strictNullChecks، یا باید ابتدا null نبودن آن‌را به صورت صریحی بررسی کرد:
  printUserInfo(user: User) {
    if (user.age != null) {
      console.log(`${user.name}, ${user.age.toString()}`);
    }
  }
در غیراینصورت قطعه کد ذیل با خطای 'Object is possibly 'undefined کامپایل نخواهد شد:
  printUserInfo(user: User) {
    console.log(`${user.name}, ${user.age.toString()}`);
  }

و یا می‌توان توسط اپراتور ! این بررسی را به صورت موقت خاموش کرد:
  printUserInfo(user: User) {
    console.log(`${user.name}, ${user.age!.toString()}`);
  }
البته استفاده‌ی از این اپراتور توسط tslint توصیه نمی‌شود:
 [tslint] Forbidden non null assertion (no-non-null-assertion)
چون بهتر است به کامپایلر عنوان نکنیم «قسم می‌خورم که این مقدار نال نیست»!



یک نکته‌ی تکمیلی
پس از آزمایش موفقیت آمیز نوع‌های نال نپذیر در TypeScript، مایکروسافت قصد دارد این ویژگی را به C# 8.0 نیز در مورد نوع‌های ارجاعی که می‌توانند نال پذیر باشند، اضافه کند (امکان داشتن نوع‌های ارجاعی نال‌نپذیر).
اشتراک‌ها
نحوه‌ استفاده از قالب Typescript library starter

Have you ever written a library in JavaScript or TypeScript? Are you planning to do it? If so, you must try Typescript library starter, a starter kit that will make easy to get started while providing all features you know to write a library in Typescript. 

نحوه‌ استفاده از قالب Typescript library starter
نظرات مطالب
آموزش TypeScript #1
بله امکان پذیر است. اما با توجه به این نکته که فلسفه وجودی TypeScript این است که در پروژه هایی با مقیاس پزرگ برای سازمان دهی کدهای سمت کلاینت مورد استفاده قرار گیرند و یکی از روش‌های سازمان دهی کدها این است که کد‌های TypeScript در فایل هایی جداگانه با پسوند ts ذخیره شده تا کامپایل و تبدیل به کد JavaScript شوند(مهم‌ترین مزیت این روش این است که از نوشتن کد‌های تکراری جلوگیری می‌شود). اما در صورتی که مایل به نوشتن کد به صورت Embed در تگ Script هستید باید از پروژه‌های متن بازی همچون TypeScript Compile یا ts-htaccess  استفاده کنید.