انومها در تایپاسکریپت و ماژولهای خارجی (Browserify)


تا به حال من از ماژول های داخلی تایپ اسکریپت استفاده می کردم و 10 تگ اسکریپت را برای بوت استرپ برنامه خود اضافه می کردم. من در حال حاضر در حال تبدیل پروژه به استفاده از ماژول های خارجی (با استفاده از مرورگرفای) هستم، اما در مورد نحوه تبدیل enums گیر کرده ام.

قبلاً چیزی شبیه به این داشتم:

mymodule.submodule {
     enum MyEnum {
        one,
        two,
        three
     }
}

و من آن را در سایر ماژولها به این صورت استفاده میکردم:

var val:mymodule.submodule.MyEnum = mymodule.submodule.MyEnum.one;

و این به درستی به JS کامپایل شد. بعد از تبدیل پروژه برای استفاده از ماژولهای خارجی، تمام اینترفیسهای خود را به فایلهای *.d.ts منتقل کردم و فکر کردم که انومها را هم آنجا قرار دهم، اما البته این باعث یک خطا شد چون هیچ نگاشتی بین انوم و اعداد در JS وجود نداشت. سپس انومها را به فایلهای *.ts منتقل کردم تا کامپایل شوند. مشکل این است که اگر آنها را اینطور بنویسم:

export enum MyEnum{
    one,
    two,
    three
}

export enum OtherEnum {
    four,
    five,
    six
}

که برای نیاز به شماره های کد من به صورت زیر کار می کند:

import Enums = require('./enums');
var val = Enums.MyEnum.one; //this works
var val1: mymodule.submodule.MyEnum = Enums.MyEnum.one; //ERROR: incompatible types

اما با نوع mymodule.submodule.MyEnum ناسازگار است. پس چگونه میتوانم هم یک اعلامیه برای نوع اینوم داشته باشم تا بتوانم نوع متغیرها را در فایلهای d.ts اعلام کنم، و هم کد واقعی اینوم تولید شده را که به آن وابسته است (تا به درستی بارگذاری شود) در فایل .ts استفاده کنم؟

توجه: این شمارشها در بسیاری از ماژولها استفاده میشوند، بنابراین قرار دادن آنها در همان فایلی که استفاده میشوند، راهحل نیست.

بهروزرسانی درباره اعلانهای اینترفیس: احتمالاً مشخص نبود که چرا اعلانهای اصلی enum را در فایلهای d.ts نگه داشتم، بنابراین یک مثال اضافه میکنم.

در فایل interfaces.d.ts من در حال حاضر دارم:

declare module mymodule.submodule {
    enum MyEnum{
       one,
       two,
       three
    }

    interface ISomething{
       aValue: MyEnum;
       aFunction: (anArg: MyEnum) => void;
    }
}

تا جایی که میدانم نمیتوانم از دستورات import در فایلهای .d.ts استفاده کنم، پس چگونه میتوانم یک اعلان enum را در همه موارد استفاده کنم؟

پاسخ شماره ۱

انومها باید در یک فایل TS باشند زیرا انومها به جاوااسکریپت کامپایل میشوند. هنگام استفاده از ماژولها، انومها باید برای استفاده وارد شوند (حتی زمانی که فقط برای تعریف نوع یک متغیر استفاده میشوند).

کد را به صورت زیر تغییر دهید:

import Enums = require('./enums');
var val1: Enums.MyEnum = Enums.MyEnum.one; // no error

همچنین، اگر این انامها در enums.ts تعریف شدهاند، نباید در mymodule.submodule باشند. آنها را از فایل تعریف حذف کنید.

در مورد بهروزرسانی

برای اینکه enum ها با رابط ها کار کنند، می توانید رابط ها را از فایل اعلان (interfaces.d.ts) خارج کنید و آنها را از یک فایل تایپ اسکریپت صادر کنید (مثلاً interfaces.ts):

import Enums = require('./enums');

export interface ISomething {
   aValue: Enums.MyEnum;
   aFunction: (anArg: Enums.MyEnum) => void;
}

سپس میتوانید از رابطها به این صورت استفاده کنید:

import Interfaces = require('./interfaces');
import Enums = require('./enums');

var example: Interfaces.ISomething = {
    aValue: Enums.MyEnum.one,
    aFunction: (example: Enums.MyEnum) => { console.log('example'); }
};