چگونه نوع یک ویژگی را در تایپاسکریپت به عنوان ترکیبی از دو ENUM تنظیم کنیم؟


من یک شمارش دارم:

enum EAlphabet = {
    A = 'A',
    B = 'B',
    C = 'C',
    D = 'D',
    E = 'E',
    F = 'F',
    G = 'G',
    H = 'H',
    I = 'I',
    J = 'J',
    K = 'K',
    L = 'L',
    M = 'M',
    N = 'N',
    O = 'O',
    P = 'P',
    Q = 'Q',
    R = 'R',
    S = 'S',
    T = 'T',
    U = 'U',
    V = 'V',
    W = 'W',
    X = 'X',
    Y = 'Y',
    Z = 'Z'
}

من یک رابط دارم و میخواهم ویژگی آن را از نوعی تعریف کنم که به صورت زیر باشد: میتواند یا 'A'، 'X'، 'D' باشد، یا میتواند 'AA'، 'JB'، 'ZE' باشد، یا میتواند 'ABC'، 'ZJE' باشد.

من مطمئن نیستم چگونه باید آن را تعریف کنم، اما چیزی شبیه به این خواهد بود؟

interface foo {
    bar: EAlphabet + EAlphabet? + EAlphabet? /* What to do here? */
}

پاسخ شماره ۱

اول از همه در چنین شرایطی من ترجیح میدهم از انجمنهای لفظی به جای Enum استفاده کنم، این کار فقط استفاده از آن را راحت میکند. متأسفانه شما نمیتوانید الحاق رشته را در سطح نوع انجام دهید، اما میتوانید نمایش را به تاپل تغییر دهید و ایمنی نوع مورد نیاز را بدست آورید.

بنابراین راه حل من دقیقاً شامل اتحاد لفظی است، اما تفاوت بین استفاده از آن با شمارنده واقعاً کوچک است.

type EAlphabet = 'A' | 'B' | 'C' | 'D'; // literal union instead of enum

interface Foo {
    bar: [EAlphabet] | [EAlphabet, EAlphabet] | [EAlphabet,EAlphabet,EAlphabet],
    toString: () => string
}

const makeFoo = (chars: Foo['bar']): Foo => ({
    bar: chars,
    toString: function () {
        return this.bar.join('');
    }
});

const example = makeFoo(['A', 'B']); // only max three allowed, works
console.log(example.toString()) // outputs AB

const example2 = makeFoo(['A', 'B', 'C', 'D']); // error wrong size
const example3 = makeFoo(['A', '*', 'C']); // error wrong sign

نقطه اصلی راه حل این است [EAlphabet] | [EAlphabet, EAlphabet] | [EAlphabet,EAlphabet,EAlphabet] ما تعریف میکنیم که نوع یا یک تاپل با 1 یا 2 یا 3 عنصر است، چیز بیشتری مجاز نیست. در ضمن اگر هر اندازهای مجاز باشد، نوع باید فقط EAlphabet[] باشد.

همچنین به طور مهم، ما میتوانیم سازنده مقدار - makeFoo را ایجاد کنیم که یک مقدار نوع معتبر میسازد، و همانطور که میبینید من تابع مفیدی به نام toString اضافه کردهام که به ما اجازه میدهد نمایش رشتهای آن را دریافت کنیم. بنابراین، حتی اگر از تاپلها در زیرساخت استفاده کنیم، در هر لحظه میتوانیم آن را به string تبدیل کنیم.

پیادهسازی آن با enum همان خواهد بود، تنها تفاوت این است که ما نیاز داریم مقادیر enum را به جای مقادیر ساده ارسال کنیم:

const example = makeFoo([EAlphabet.A, EAlphabet.B]); 

پاسخ شماره ۲

اینطور نیست که شمارشها (enums) اینگونه کار کنند، و احتمالاً این بهترین راه برای رسیدن به این هدف هم نیست. ممکن است نیاز باشد آن را بهصورت رشته تعریف کنید و بررسی regex خود را انجام دهید تا ببینید آیا ۲ تا ۳ کاراکتر دارد، و غیره.

تو میتونی (اما احتمالاً نباید) چیزی شبیه این انجام بدی.

// Array of EAlphabet with 2-3 Elements
export interface foo {
  [0]: EAlphabet;
  [1]: EAlphabet;
  [2]?: EAlphabet;
}

let a: foo;
a = [EAlphabet.A, EAlphabet.X, EAlphabet.D];

به خاطر داشته باشید که

a = ['A', 'B']

هنوز اینطور کار نخواهد کرد.